我有一组具有相同功能但具有不同逻辑的类。但是,每个类函数都可以返回许多对象。将返回类型设置为接口是安全的吗?
每个类(都使用相同的接口)使用不同的业务逻辑来执行此操作。
protected IMessage validateReturnType; <-- This is in an abstract class
public bool IsValid() <-- This is in an abstract class
{
return (validateReturnType.GetType() == typeof(Success));
}
public IMessage Validate()
{
if (name.Length < 5)
{
validateReturnType = new Error("Name must be 5 characters or greater.");
}
else
{
validateReturnType = new Success("Name is valid.");
}
return validateReturnType;
}
单元测试功能的返回类型是否存在任何缺陷?另外,为了让它们成功运行需要运行的功能,它被认为是不好的设计吗?在此示例中,必须在IsValid()之前运行Validate(),否则IsValid()将始终返回false。
谢谢。
答案 0 :(得分:10)
但是,每个类功能都可以 返回一些对象。这很安全 将返回类型设置为 接口
这是一种很好的做法并且很常见。例如,看看COM的构建方式,它很大程度上依赖于这种方法。
单元测试函数的返回类型是否存在任何缺陷
没有
另外,为了让它们成功,需要运行功能被认为是不好的设计吗?在此示例中,必须在IsValid()之前运行Validate(),否则IsValid()将始终返回false。
这对于使用面向对象的编程范例来说很好,例如使用套接字。在发送和接收数据之前,通常会有一个connect方法。
据说,保持较少的状态比通常更多的状态更好,因为以这种方式更容易证明你的程序是正确的。例如,您必须以一种方式测试依赖于此函数的每个函数,而不是现在以两种方式。如果您有很多州,可能的计划状态会呈指数级增长。如果您对州为何是一件坏事感兴趣,请查看functional programming。
答案 1 :(得分:4)
另外,为了让它们成功,需要运行功能被认为是不好的设计吗?在此示例中,必须在IsValid()之前运行Validate(),否则IsValid()将始终返回false。
有一些例外,但一般来说,你应该避免构建这种API。这被称为“时间依赖”,这只是“一件事需要在另一件事之前发生”的一个奇特用语。时间依赖性的问题在于它们很少是自我描述的。换句话说,API本身不会如何使用它。依赖于时间依赖性的API通常比类似的代码更难以直观地理解和使用。
在您的示例中,我考虑使用以下设计目标重构API:
如果您必须拥有IsValid,请重新定义它以检查#3。如果要缓存结果以便不必经常重新计算IsValid,请考虑实现INotifyPropertyChanged并使PropertyChanged上的缓存结果无效。
答案 2 :(得分:1)
将接口作为返回类型是好的,因为您的方法将与更多类型的消息兼容。
答案 3 :(得分:1)
返回接口通常很好,因为它隐藏了实现。 (当然,你不应该隐藏超过必要的......)
在你的例子的情况下,我有点担心你想要对你的函数的实际返回类型进行单元测试,而使用接口的点就是隐藏它。看起来您的实际代码将依赖于实际的返回类型,而 会闻起来很糟糕。
我最好向IsValid()
添加一个抽象方法IMessage
,在Success
和Error
中覆盖它,然后直接调用validateReturnType.IsValid()
。对我来说听起来更多OO。 OO和虚拟方法的目标是避免基于类型的案例切换,就像您在IsValid()
中所做的那样。