C# 我可以用C语言将组合和继承与接口结合起来吗#
我有一个设计问题,我想不出来。以下是我得到的: 通常,我有两种类型的对象和选项。这些被抽象为两个接口IStrike和IOption 假设IOption有以下字段,实际上大约是10倍,但我们可以使用以下三个字段来说明问题C# 我可以用C语言将组合和继承与接口结合起来吗#,c#,c#-4.0,C#,C# 4.0,我有一个设计问题,我想不出来。以下是我得到的: 通常,我有两种类型的对象和选项。这些被抽象为两个接口IStrike和IOption 假设IOption有以下字段,实际上大约是10倍,但我们可以使用以下三个字段来说明问题 interface IOption { double Bid{get;set;} double Ask{get;set;} double ImpliedVol{get;set;} } interface IStrike { IOption Call{g
interface IOption
{
double Bid{get;set;}
double Ask{get;set;}
double ImpliedVol{get;set;}
}
interface IStrike
{
IOption Call{get;set;}
IOption Put{get;set;}
}
现在,这一切都很好,但假设我有下面的方法来对IOption执行一些“数学”运算
public double SquareImpliedVol(IOption opt)
{
return Math.Pow(opt.ImpliedVol,2);
}
同样,这不是问题,但当我为测试编写一些模拟对象时,我不清楚是否需要实现Bid和Ask。我不知道,但我不知道,除非我知道SquareImpliedVol中的胆量,这意味着我正在针对代码编写测试,这很糟糕
为了解决这个问题,我可以创建另一个只包含ImpliedVol属性的接口ioptionmpliedvol,然后让IOption像这样从ioptionmpliedvol继承
interface IOption : IOptionImpliedVol
{
double Bid{get;set;}
double Ask{get;set;}
}
然后我们可以切换到SquareImpliedVol
public double SquareImpliedVol(IOptionImpliedVol opt)
{
return Math.Pow(opt.ImpliedVol,2);
}
我们很好。我会写模拟对象,一切都很美好。除了……我想写一个对列表进行操作的方法,但是我需要的唯一属性是Call.ImpliedVol和Put.ImpliedVol。我想创造一些像
interface IStrikeImpliedVol
{
IOptionImpliedVol Call;
IOptionImpliedVol Put;
}
然后我也可以
interface IStrike : IStrikeImpliedVol
{
IOption Call;
IOption Put;
}
但那是不合法的。我觉得必须要有某种设计模式才能解决这个问题,但我陷入了某种组合和继承的网络中。我认为您最初设计的两个接口是正确的。你是说你必须知道什么时候设置
Bid/Ask
,什么时候不在测试中设置,这让你很烦恼
让我们试着从另一个角度来看它。您正在为某个函数编写测试(假设它是您的SquareImpliedVol
)。您知道,正确实现此函数应该只关心ImpliedVol
属性,而不关心Bid/Ask
,因此可以将这些属性留空。如果函数在未设置的情况下失败,那么您的单元测试发现了一个问题-请高兴。当然,如果空的Bid/Ask
是选项
对象的不正确状态,则它会有所不同,但在您的情况下,这似乎不是问题
换言之,我想说的是,您正在根据您的知识编写一个测试,测试特定方法应该如何工作,并且这个知识与该函数中已经编写的代码相关,这一点没有错。有很多方法可以处理这个问题,但主要问题是您期望的解决方案是什么,不是其他人怎么处理的 例如,许多人会用模拟对象来解决“测试接受IOption对象的东西”,但他们当然不会关心实际使用了IOption的哪一部分。也就是说,这有点错误,因为如果您开始查看使用模拟库生成模拟对象的代码,他们清楚地知道使用了接口的哪一部分,因为他们将编写如下代码:
var mock = CREATE MOCK OF TYPE IOption
ON MOCK mock, EXPECT CALL TO ImpliedVol
FOR THAT CALL, RETURN 15
test code
VERIFY THAT CALLS WERE MADE AS EXPECTED
如果您对此感到满意,我将使用一个普通的模拟库,如NMock或类似的库,为您的接口生成模拟对象。使用这些库,您还可以说“我不希望在代码期间调用投标”,因此它应该适合您
然而,你碰到了一些很难测试和量化的东西。是的,你可以证实预期的副作用确实发生了。除非你知道所有副作用,否则你如何确认没有其他副作用发生?例如,如果将来有人向接口添加一个新方法,该怎么办。如何确保所有单元测试,或其中任何单元测试,或无单元测试,验证对该额外方法的调用从未为现有测试调用过
这有关系吗?+1与最初的设计是正确的想法有关。我很确定您不想使用
ioptionmpliedvol
和IStrikeImpliedVol
接口;什么时候结束?你自己(Jonathan)已经用了一个非常恰当的术语来描述这条引导你走下的道路:一个混乱、复杂的网络。听雪熊的,谢谢。有时候我会对设计有点迂腐,当我认为可能会发生这种情况时,有一个像StackOverflow这样的社区可以与我交谈是件很棒的事情。