假设您在Value对象和Services对象中划分系统(如"面向对象的软件增长,测试指导"中所述.Misko Hevery称这些为"newables"和"injectables".
当你的一个值对象突然需要访问服务来实现它的方法时会发生什么?
假设你有一个很好的简单Value对象.它是不可变的,包含一些信息,而且就是它.假设我们使用类似这样的东西:
CreditCard card = new CreditCard("4111-1111-1111-1111", "07/10");
if (card.isValid())
{
// do stuff
}
else
{
// don't do stuff
}
Run Code Online (Sandbox Code Playgroud)
到现在为止还挺好. isValid()在卡号上实现校验位算法并返回true/false.
现在,假设我希望通过验证当前时间的到期日来增强系统.您如何在不破坏Value对象/服务对象paradim的情况下完成此操作?我希望这个课程能够继续进行单元测试.
CreditCard 现在有一个依赖项,但由于它的创建方式,它无法注入,因此依赖注入已经完成.CreditCard类不应该呼唤单身(我的位置,为一个Singleton全球访问是不好的做法)CreditCardVerificationService.validateCard()手段意味着必须重新访问所有现有代码.isValid()的实现正在泄漏.我知道有一些事情可以解决这个问题,但最干净的方法是什么?
编写代码时,我们应该能够识别两大对象:
http://www.loosecouplings.com/2011/01/how-to-write-testable-code-overview.html
http://misko.hevery.com/2008/09/30/to-new-or-not-to-new/
可注入对象是在其构造函数中公开依赖项的对象(服务),这些依赖项通常使用IoC容器解析,这些对象只能在其构造函数中请求其他注入项
Newable是在其构造函数中也暴露依赖项的对象,但是newables只能请求其他可新建对象(实体,值对象),新对象的另一个特征是它们不应该持有对可注入对象的引用
但是在编写代码时,我们经常需要将一个服务(可注入)"注入"到一个实体(newable)中
我一直在想,在一个新的对象中暴露服务依赖可能更好地在方法级别进行,但这听起来有很多工作要做....只是考虑在每次调用方法时解析依赖关系...这有点像我们必须使用服务定位器反模式
我解决这个问题的方法是:
使用公开依赖项的方法创建一个接口(该方法中将使用该服务)
为接口创建一个扩展方法,并将其放在不同的命名空间中,也许放在另一个程序集中,然后将调用包装到原始方法,使用服务定位器解析依赖项
这样做,我们可以在新的和可注射的对象之间保持一致的分离,并且能够轻松地在我们的新手中使用服务
extension-methods dependency-injection service-locator injectable newable
我试过这个,但它不起作用.Foo只是对有效的测试.Bar是真正的尝试,它应该接收任何新的类型,但Object的子类无法用于此目的.
class A {
}
class B {
public Foo(newable: typeof A):void {
}
public Bar(newable: typeof Object):void {
}
}
var b = new B();
b.Foo(A);
b.Bar(A); // <- error here
Run Code Online (Sandbox Code Playgroud)