假設我有一些DDD服務需要一些IEnumerable<Foo>
來執行一些計算。我想出了兩種設計:我是否應該將存儲庫接口與域模型分離
摘要與
IFooRepository
接口的數據訪問,這是相當典型的public class FooService { private readonly IFooRepository _fooRepository; public FooService(IFooRepository fooRepository) => _fooRepository = fooRepository; public int Calculate() { var fooModels = _fooRepository.GetAll(); return fooModels.Sum(f => f.Bar); } }
不要依賴
IFooRepository
抽象和注入IEnumerable<Foo>
直接public class FooService { private readonly IEnumerable<Foo> _foos; public FooService(IEnumerable<Foo> foos) => _foos = foos; public int Calculate() => _foos.Sum(f => f.Bar); }
這第二個設計s在我看來,更好的是FooService
現在不關心數據來自何處,Calculate
變成純粹的域邏輯(忽略IEnumerable
可能來自不純的來源)。
使用第二個設計另一種說法是,當IFooRepository
通過網絡進行異步IO,它通常會希望使用async-await
,如:
public class AsyncDbFooRepository : IFooRepository
{
public async Task<IEnumerable<Foo>> GetAll()
{
// Asynchronously fetch results from database
}
}
但是當你需要async all the way down,FooService
現在不得不將其簽名更改爲async Task<int> Calculate()
。這似乎違反了dependency inversion principle。
但是,第二個設計也存在問題。首先,你必須依靠的DI容器(使用簡單注射器在這裏舉例),或組成根源上解決,如數據訪問代碼:
public class CompositionRoot
{
public void ComposeDependencies()
{
container.Register<IFooRepository, AsyncDbFooRepository>(Lifestyle.Scoped);
// Not sure if the syntax is right, but it demonstrates the concept
container.Register<FooService>(async() => new FooService(await GetFoos(container)));
}
private async Task<IEnumerable<Foo>> GetFoos(Container container)
{
var fooRepository = container.GetInstance<IFooRepository>();
return await fooRepository.GetAll();
}
}
而且在我的具體情況,AsyncDbFooRepository
需要某種的運行參數來構建,這意味着您需要一個abstract factory來構造AsyncDbFooRepository
。
隨着抽象工廠,現在我必須管理所有依賴AsyncDbFooRepository
(AsyncDbFooRepository
下的對象圖是不平凡的)的生命週期。我有一種預感,如果我選擇第二種設計,我會錯誤地使用DI。
總之,我的問題是:
- 我在我的第二個設計不當使用DI?
- 我該如何爲我的第二個設計令人滿意地構建我的依賴關係?
如果Foo是運行時數據,則不應將其注入到組件構造函數中。閱讀:https://cuttingedge.it/blogs/steven/pivot/entry.php?id = 99 – Steven
感謝您的鏈接。根據你的博客,我應該注入'AsyncDbFooRepository'而不是(首次設計),但是這不會違反依賴倒置原則(如問題所述)嗎? – rexcfnghk
我會建議你使用存儲庫層。您可以擁有SqlFooRepository,FileSystemFooRepository,Neo4JFooRepository等。您可以從數據更改位置獲取好處。如果您在構造函數中通過IEnumerable,則會限制自己,例如將數據添加回存儲庫,刪除等。 –
user1628733