バックグラウンド
私自身の理解のために、私は単純なシナリオの階層化アーキテクチャを作成しようとしています。単純なドメインクラスCarがあります。
public class Car {
public string Make;
public string Model;
public int Year;
public Accelerate() { }
public Decelerate() { }
}
データベースから値を入力するCarの新しいインスタンスを作成したいと思います。 これは私が立ち往生しているところです。
永続層には、CarIDに基づいてデータベースからこれらの値を取得するという汚い作業を行う別のクラス(CarRepositoryと呼ばれる)が必要だと思います。
このCarRepository依存関係を実行時にCarドメインクラスに注入して、さまざまな実装(単体テストの偽物など)を可能にしたいと考えています。
だから、私はこれをCarクラスに追加することを検討します:
public class Car() {
private ICarRespository _carRepository;
public Car(ICarRepository carRepository) {
_carRespository = carRepository;
}
public void Find(int carId) {
var car = _carRepository.FindById(carId);
this.Make = car.Make;
this.Model = car.Model;
// etc.
}
// other properties and methods here
}
そして、ICarRepositoryを次のように定義します。
public interface ICarRepository {
DtoCar FindById(int carId);
}
public class DtoCar {
public string Make;
public string Model;
public int Year;
}
「貧乏人の依存性注入」を使用していて、プロジェクトタイプ(本番コードと単体テスト)に基づいて、集約ルートが適切な具象CarRespositoryに合格できるようにしていると仮定します。明らかに、ここではコンストラクタインジェクションを使用することを選択しました。
質問
(1)この解決策は正しくないと感じています。新しい車を作成するときは、その時点ですべてのプロパティを設定して初期化する必要があると感じています。ただし、Find()メソッドを呼び出した後でのみ、実際に有効な車になることができます。検索に有効なCarIDを渡さないとどうなりますか?そうすると、Carオブジェクトが有効なオブジェクトになることはありません。これは私を悩ませるべきではありませんか?もっと良い方法はありますか?
(2)コンストラクターインジェクションを使用してリポジトリの依存関係を渡します…CarIDを渡して、コンストラクターでここを検索することもできますか…次に、Find()メソッドを削除できますか?それで:
public Car(ICarRepository carRepository, int carId) {
_carRespository = carRepository;
var car = _carRepository.FindById(carId);
this.Make = car.Make;
this.Model = car.Model;
// etc.
}
...こんな風になっているのを見たことがないので、使うのをためらっています。このようにしても大丈夫ですか?
(3)ここで欠けている創造的なパターンはありますか?これは単純なシナリオです…Factory、Singleton、Prototypeなどがここに当てはまるとは思いません(誤解される可能性があります)。それらは重くて専門的だと感じます。このシナリオ(データベースからの単純なドメインオブジェクト)は非常に基本的なように思われるため、何らかのガイダンスが必要です。