ドメイン モデル パターンに従って、ドメイン エンティティに対しても動作する必要があります。データ アクセスにエンティティ フレームワークを使用しています。すべてのエンティティを抽出し、部分クラスとしてドメイン層に移動しました。これで、ドメイン レイヤーに別の部分クラスのセットがあり、動作がリポジトリと通信します。問題は、ドメイン モデル内のエンティティも参照するリポジトリが循環参照につながることです。
誰でもこのための設計ソリューションを提供できますか?
ドメイン モデル パターンに従って、ドメイン エンティティに対しても動作する必要があります。データ アクセスにエンティティ フレームワークを使用しています。すべてのエンティティを抽出し、部分クラスとしてドメイン層に移動しました。これで、ドメイン レイヤーに別の部分クラスのセットがあり、動作がリポジトリと通信します。問題は、ドメイン モデル内のエンティティも参照するリポジトリが循環参照につながることです。
誰でもこのための設計ソリューションを提供できますか?
抽象的な言葉で話すのは難しいので、ここに役立つ例があります。Car
旅行に行けるサービスがあると想像してみてください。この旅行中Car
に、ガスが不足し、オイルを交換する必要が生じることがあります。
class Car {
private GasTank gasTank;
private OilPan oilPan;
double MPG = 25.0;
void drive( int distance ) {
gasTank.consume( distance / MPG );
oilPan.dirty( distance / OilDirtyRate ); // Making up a term here...but Oil gets dirty
}
void fillUp() {
gasTank.fillUp();
}
void changeOil() {
oilPan.empty();
oilPan.add( new Oil() );
}
}
// These are value objects, there's no identity here
class GasTank { } // Imagine above methods defined
class OilPan { } // more methods
class CarRepository {
Car findByVIN( String vin ) {
// Search Car collection or database
return car;
}
boolean register( Car car ) {
carDao.insert( car.toDTO() );
}
boolean update( Car car ) {
// write to persistence, etc.
}
}
class TripService {
private CarRepository carRepo;
void takeTrip( String carVin, int milesToGo ) {
Car car = carRepo.findByVIN( carVin );
// calculate distance
while ( milesToGo > 0 ) {
car.drive( 200 );
milesToGo -= 200;
if ( car.isOutOfGas() ) {
car.fillUp();
}
if ( car.needsOilChange() ) {
car.changeOil();
}
}
carRepo.update( car );
}
}
さらに別の車の例 (および C# を話しているので Java) を使用して申し訳ありませんが、Car にはまだロジックがありますが、TripService は Car を全体として操作できることがわかります。車は、ガスの消費やオイルの汚れなど、その内部ロジックを処理する責任があります。タンクdrive
に十分なガスがない場合、実際に走行した距離を返す場合があります。通常の発生でない場合は、例外がスローされる可能性があります。このdrive
メソッドは、車が始動しているか、オイルが入っているか、ガスが入っているか、シート ビートが固定されているかどうかも確認できます。車を始動すると、異なる速度でガスが消費される可能性があります。TripService (「アプリケーション」) が と通信してCarRepository
操作していることCar
がわかりますが、Car
については何も認識してCarRepository
いませんが、まだロジックを持っています。
ガスやオイルの交換を処理することはTripService
、実際には責任を負わないかもしれませんが、車の摩耗をシミュレートするアプリケーションでは、それらの責任を負う可能性があります。
抽象的な用語に戻ると、サービスはリポジトリやファクトリとやり取りしてドメイン オブジェクトを取得します。次に、必要に応じてドメイン オブジェクト間の相互作用を調整します。結局のところ、何かがドメイン オブジェクトに何をすべきかを伝える必要があります。そこでサービスの出番です。ドメイン オブジェクトは、永続性を無視しているため、リポジトリについて何も知りません。それ自体がどのように永続化されるかを知っていても、ビジネス ロジックには影響しないため、ドメイン オブジェクト内でそれを処理しません。ビジネスロジックを処理し、不変条件を維持するだけです。リポジトリは、ドメイン オブジェクトを保持して取得しているため、ドメイン オブジェクトについて認識している必要があります。