1)ドメイン レイヤーがインフラストラクチャ サービス ISを使用している場合、そのインターフェイスはドメイン レイヤー内で定義され、その実装はインフラストラクチャ レイヤー内で定義されます。
IS (リポジトリや電子メール サービスなど) をドメイン エンティティに直接挿入するべきではありません。
class Foo
{
IRepository repo;
...
public int DoSomething()
{
var info = repo.Get...;
...
}
}
代わりに、ドメイン エンティティの何らかのメソッドが特定のISを必要とする場合、アプリケーション レイヤーはそのISを引数としてそのメソッドに渡すことができます。
class Foo
{
...
public int DoSomething(IRepository repo)
{
var info = repo.Get...;
...
}
}
a) ISもDomain Servicesに直接注入すべきではないと思います:
class TransferService
{
IRepository repo;
...
public bool Transfer()
{
var info = repo.Get...;
...
}
}
、代わりにISを使用するドメイン サービスのメソッドに引数として渡す必要があります。
class TransferService
{
public bool Transfer(IRepository repo)
{
var info = repo.Get...;
...
}
}
b)ドメインエンティティのメソッドがドメインサービスを使用する必要がある場合、引数を介してそれを受け取る必要はないと思います(ドメインサービスを引数として渡すと、メソッドの依存関係を明示的に伝えるという利点があります)が、代わりに呼び出すことができますドメインエンティティとドメインサービスの両方がドメインの概念であるためです。
class Foo
{
...
public int DoSomething()
{
var info = TransferService.Transfer(...);
...
}
}
アップデート:
1)
機能のために IS が必要な場合は、IS をドメイン サービスに挿入できます。つまり、メソッドに渡されません。これはエンティティとは異なります。これは、ドメイン サービスがステートレスであるため、必要な依存関係を一度構成して、必要な場所 (他のエンティティなど) で使用できるためです。
a)ドメイン エンティティにISを注入してはならない主な理由は、そのステートフルな性質によるものですか?
b) しかし、ドメイン エンティティにISを注入しない主な理由は、持続性無視ルールに違反するからだと思いましたか?
c) ISを注入した場合、エンティティのステートフルな性質はどのような問題を引き起こしますか?
d)ドメイン サービスにISを挿入することは PI に違反しませんか? そうでない場合、なぜですか?
2)
ドメイン サービスは、リポジトリ インターフェイスを引数として渡すのと同じように、引数としてエンティティに渡す必要があります。同じ原則が適用されます。
しかし、リポジトリとは異なり、ドメイン サービスはドメインの概念です。「同じ原則が適用される」とはどういう意味ですか? つまり、Domain ServiceをDomain Entityに注入してもPIに違反しませんが、 Repositoryを注入してもPI に違反します!
2 番目の更新:
1)
a)
それが一つの理由です。もう 1 つは、不必要なカップリングを作成することです。エンティティの 1 つの動作だけにリポジトリが必要な場合、それを常にエンティティに挿入するのはなぜでしょうか? また、これらの依存関係を解決する方法を検討する必要がありますか? エンティティを依存性注入グラフの一部にしますか? これにより、エンティティの責任が急速に過負荷になります。
したがって、私の理解が正しければ、ISをドメイン サービス DSに挿入しても SRP に違反しません。これは、 DSが指定されたタスク (つまり、指定された責任) を実行するためにそれを使用しているためです。一方、ドメイン エンティティにISを挿入することは、主な責任であるため、SRP に違反しています。のドメイン エンティティはそのライフ サイクルとアイデンティティに焦点を当てていますが、ほとんどの場合、ISはこれら 2 つのタスクを管理する上で不可欠な部分ではありません (つまり、ライフ サイクルとアイデンティティに焦点を当てています)。
b)
IS をドメイン エンティティ メソッドに渡すことはできますが、実装ではなくインターフェイスを渡しているため、ここでの問題は PI の違反にはなりません。ドメイン メソッドが IS インターフェイスで 1 つのメソッドしか使用しない場合、問題は SRP 違反になります。
I - しかし、以前の投稿のいくつかで、 ISをDomain Entityのメソッドに引数として渡しても問題ないと述べていましたが、ここでは、このドメイン メソッドがISインスタンスで 1 つのメソッドのみを使用すると、SRP に違反するとおっしゃっていますか?
II - ISが単一のメソッドを含む役割ベースのインターフェースを実装し、代わりにこの役割ベースのインターフェースをドメイン メソッドの引数として渡す場合、これを SRP 違反とみなしますか? そうでない場合、なぜですか?
d)
PI はインターフェイスを使用して維持されます。
ドメインメソッドがインターフェースを介してリポジトリを参照している場合でも、PI の違反と見なされることを何度か読みました。なぜそれに同意しないのですか?
2)
ただし、非常に明示的である方がよいでしょう。したがって、リポジトリを渡してエンティティにサービスを提供することを暗黙のうちに理解する代わりに、提供された機能を独自のインターフェイスとして宣言し、エンティティがそれに依存するようにします。
a) それでは、ドメイン サービスをドメイン エンティティに注入しない唯一の理由は、SRP の違反によるものですか?
b)
提供された機能を独自のインターフェースとして宣言する
ロールベースのインターフェースを使用することを提案していると思いますか? しかし、役割ベースのインターフェイス (たとえば Domain Service によって実装されたもの) を Domain Entity に注入しても、SRPの違反が発生することはありません。 !
ドメイン エンティティのメソッドにISを渡すことに関して、あなたと Aaron Hawkins は反対側にいるようです ?!
3 番目の更新:
1)
a)
したがって、私の理解が正しければ、IS をドメイン サービス DS に挿入しても SRP に違反しません。これは、DS が指定されたタスク (つまり、指定された責任) を実行するためにそれを使用しているためです。一方、ドメイン エンティティに IS を挿入することは、主な責任であるため、SRP に違反しています。ドメイン エンティティのほとんどは、そのライフ サイクルとアイデンティティに焦点を当てていますが、ほとんどの場合、これら 2 つのタスクを管理する上で不可欠な部分ではありません (つまり、ライフ サイクルとアイデンティティに焦点を当てています)。
はい、それは正しく、主な理由の 1 つです。
I - ISをドメイン エンティティ DEに挿入することによって、このDEが SRP に違反することは完全に合理的に思えます。なぜなら、 ISはDEに指定された 2 つのタスクの管理に貢献しないからです。
しかし、このシナリオをより詳細に想像しようとすると、少し難しくなります。つまり、DEのメソッドが2 つの指定されたタスク (つまり、そのライフサイクルとアイデンティティ) の管理に焦点を当てている場合、これらのメソッドのいずれかがISを必要とする場合、2 つの指定されたタスクを達成するためにISが必要であると仮定するのは合理的ではないでしょうか? DE のライフ サイクルと IDに関係のない他のタスクではありませんか? はいの場合、 DEが SRP に違反しているとどのように主張できますか?
II - DE のライフ サイクルと IDを管理することの正確な意味を想像するのも困難です。まず、DEに ID が割り当てられると、この ID は変更されません。では、そのアイデンティティについてはどう管理する必要があるのでしょうか?
III - DE のライフサイクルを管理するとはどういう意味ですか? おそらく、データの一貫性を保つDEの不変条件を定義するか...?
IV - 実世界のエンティティが実行する他のすべてのタスク (つまり、DE のライフ サイクルと ID に関連しないもの) は、DEから除外して関連オブジェクトに入れる必要がありますか?
d)
IS が 1 つのメソッドを含む役割ベースのインターフェイスを実装し、代わりにこの役割ベースのインターフェイスをドメイン メソッドの引数として渡す場合、これを SRP 違反と見なしますか? そうでない場合、なぜですか?
それを行うのはひどいことではありませんが、SRP に違反する可能性があります。
ISをDEに挿入するとISPに違反する可能性があるとどのように主張できるかわかりません。私の知る限り、 ISPはこのインターフェイスを実装するオブジェクトによってのみ違反される可能性があり、このインターフェイスの実装が挿入されるオブジェクトによって違反される可能性があるからです。
4 回目の更新:
SRP は当初考えていたよりもはるかに複雑であることに気付き始めています
a)
通常は状態の変更を伴うエンティティに関連付けられた動作も、エンティティに配置する必要があります。そのような動作でサービスを使用する必要がある場合は、そのサービスを渡しますが、通常はエンティティにできるだけ多くの動作を配置するようにします。
Dog
IV – 1 次の動作メソッドには状態の変更は含まれていませんが、それらもエンティティに属する必要があると思います。
class Dog
{
...
void DoBark();
void DoFetch();
void DoGuard();
Breed GetBreed();
Pedigree GetPedigree();
Snack FavSnack();
}
IV – b)および行動方法GetBreed
は? はいの場合、プロパティ、およびも動作と見なす必要があります。これらは本質的に同じ機能を提供するためです ( 、および重い計算を行わず、単にオブジェクトを返すと仮定します) 。GetPedigree
FavSnack
Breed
Pedigree
Snack
GetBreed
GetPedigree
FavSnack
class Dog
{
...
void DoBark();
void DoFetch();
void DoGuard();
Breed Breed { get{...} }
Pedigree Pedigree { get{...} }
Snack Snack { get{...} }
}
IV – c) 上記のプロパティにもsetterがある場合、それらには状態変更動作が含まれていると言えますか?
IV – d)
通常は状態の変更を伴うエンティティに関連付けられた動作も、エンティティに配置する必要があります。
しかし、ドメイン エンティティの主な責任がそのライフ サイクルの管理である場合、ライフ サイクルの管理に関係のない動作を含めないことは、SRP の違反になります (上記の例でDog.DoBark
は、Dog
「のライフサイクル)?!
d)
私。
IS を DE ビヘイビア メソッドに渡す方が優れていますが、IS インターフェイスに目前のビヘイビアに関係のないものがたくさんある場合、SRP/ISP に違反する可能性があります。これは ISP の基本的な前提です。依存関係は、たまたま必要な機能を含む肥大化したインターフェイスとは対照的に、特定のインターフェイスに作成する必要があります。
そのため、ISが DE の動作メソッドの 1 つに引数として渡された場合、目の前の動作に関係のない操作がいくつかありますが、DE のメソッドMは、 Mが処理する必要がある動作に関係のないISのメソッドを使用しません。 SRP/ISP に違反していませんか?
Ⅱ.– あなたの言っていることは理解できますが、次の ISP の定義によれば、この用語は、特定のインターフェースを実装するオブジェクトServObjが ISP に違反していることを示すためにのみ使用されるべきであるという事実から、私の混乱が生じます。注入されたのは SRP に違反しています ( ServObjを受け取ったため):
インターフェイス分離の原則は、責任の結合を扱うという点で単一責任の原則に似ています。実際、ISP は、オブジェクトのパブリック インターフェイスへの SRP のアプリケーションとして理解できます。
ISP は、ある程度、単一責任原則のサブセット、またはより具体的な形態と見なすことができます。ただし、ISP の見方の変化は、特定のクラスまたはモジュールのパブリック API を調べます。
ありがとうございました