fea*_*net 14 c# dependencies unit-testing design-patterns dependency-injection
据我所知,DI的优点是:
假设我有一个存储库OrderRepository,它充当通过Linq到Sql dbml生成的Order对象的存储库.我无法使我的订单存储库通用,因为它执行Linq Order实体和我自己的Order POCO域类之间的映射.
由于OrderRepository必然依赖于特定的Linq to Sql DataContext,因此无法真正说明DataContext的参数传递使代码可重用或以任何有意义的方式减少依赖性.
它还使代码更难阅读,以实例化我现在需要编写的存储库
new OrdersRepository(new MyLinqDataContext())
另外与存储库的主要目的相反,即抽象/隐藏DataContext的存在以消耗代码.
所以一般来说我认为这将是一个非常可怕的设计,但它会带来便利单元测试的好处.这有充分的理由吗?还是有第三种方式?我对听取意见非常感兴趣.
Rob*_*Rob 12
依赖注入的主要优点是测试.当我第一次开始采用测试驱动开发和DI时,你已经找到了一些对我来说很奇怪的东西.DI确实破坏了封装.单元测试应测试与实现相关的决策; 因此,您最终会暴露出纯粹封装的场景中不会出现的细节.您的示例很好,如果您没有进行测试驱动开发,您可能希望封装数据上下文.
但是你说的,因为OrderRepository必然依赖于特定的Linq到Sql DataContext,我不同意 - 我们有相同的设置,只依赖于接口.你必须打破这种依赖.
然而,让您的示例更进一步,如何在不运行数据库的情况下测试您的存储库(或其客户端)?这是单元测试的核心原则之一 - 您必须能够在不与外部系统交互的情况下测试功能.没有比数据库更重要的了.依赖注入是一种模式,可以打破子系统和层的依赖关系.没有它,单元测试最终需要大量的夹具设置,变得难以编写,易碎且太慢.结果 - 你不会写它们.
让你的榜样更进一步,你可能会
在单元测试中:
// From your example...
new OrdersRepository(new InMemoryDataContext());
// or...
IOrdersRepository repo = new InMemoryDataContext().OrdersRepository;
Run Code Online (Sandbox Code Playgroud)
和生产中(使用IOC容器):
// usually...
Container.Create<IDataContext>().OrdersRepository
// but can be...
Container.Create<IOrdersRepository>();
Run Code Online (Sandbox Code Playgroud)
(如果你没有使用过IOC容器,它们就是使DI工作的粘合剂.把它想象成对象图的"make"(或ant)......容器为你构建依赖图并完成所有的繁重的施工).在使用IOC容器时,您将获得在OP中提到的依赖项隐藏.依赖关系由容器配置和处理,作为一个单独的关注点 - 调用代码可以只询问接口的实例.
这本书非常出色,详细探讨了这些问题.查看由Mezaros提供的xUnit测试模式:重构测试代码.这是将您的软件开发能力提升到新水平的书籍之一.
| 归档时间: |
|
| 查看次数: |
924 次 |
| 最近记录: |