5

我有一组具有相同功能但逻辑不同的类。但是,每个类函数都可以返回多个对象。将返回类型设置为接口是否安全?

每个类(都使用相同的接口)使用不同的业务逻辑执行此操作。

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;
}

单元测试函数的返回类型是否有任何陷阱?另外,为了让它们成功而需要运行功能是否被认为是糟糕的设计?在此示例中,Validate() 必须在 IsValid() 之前运行,否则 IsValid() 将始终返回 false。

谢谢你。

4

4 回答 4

10

但是,每个类函数都可以返回多个对象。将返回类型设置为接口是否安全?

这是很好的做法并且很常见。例如,看看 COM 的构建方式,它在很大程度上依赖于这种方法。

单元测试函数的返回类型是否有任何陷阱

不。

另外,为了让它们成功而需要运行功能是否被认为是糟糕的设计?在此示例中,Validate() 必须在 IsValid() 之前运行,否则 IsValid() 将始终返回 false。

这对于使用面向对象的编程范式来说很好,例如使用套接字。在发送和接收数据之前,通常有一个连接方法。

话虽这么说,作为一般规则,保持更少状态比保持更多状态更好,因为这样更容易证明你的程序是正确的。例如,您现在必须测试依赖此函数的每个函数,而不是以一种方式,而是以两种方式。如果您有很多状态,可能的程序状态会呈指数增长。如果您对为什么状态是一件坏事感兴趣,请查看函数式编程。

于 2010-06-14T02:05:02.283 回答
4

另外,为了让它们成功而需要运行功能是否被认为是糟糕的设计?在此示例中,Validate() 必须在 IsValid() 之前运行,否则 IsValid() 将始终返回 false。

也有例外,但通常您应该避免构建这种 API。这被称为“时间依赖性”,这只是“一件事必须先于另一件事发生”的花哨术语。时间依赖的问题在于它们很少是自我描述的。换句话说,API 本身不会传达它的预期使用方式。依赖于时间依赖性的 API 通常比类似的代码更难直观地理解和使用。

在您的示例中,我会考虑使用以下设计目标重构 API:

  1. 完全摆脱 IsValid。
  2. 验证返回验证错误列表。
  3. 将“成功”重新定义为让 Validate() 返回一个没有错误的空列表。

如果您只是必须具有 IsValid,请重新定义它以检查 #3。如果要缓存结果以便不必不断地重新计算 IsValid,请考虑实现 INotifyPropertyChanged 并使 PropertyChanged 上的缓存结果无效。

于 2010-06-14T12:43:01.513 回答
1

将接口作为返回类型很好,因为您的方法将与更多类型的消息兼容。

于 2010-06-14T02:05:14.407 回答
1

返回接口通常是好的,因为它隐藏了实现。(当然,你不应该隐藏不必要的东西......)

不过,在您的示例中,我有点担心您想要对函数的实际返回类型进行单元测试,而使用接口的目的正是为了隐藏它。看起来您的实际代码将依赖于实际的返回类型,闻起来很糟糕。

最好给 加个抽象方法IsValid(),在andIMessage中重写,直接调用。对我来说听起来更OO。OO 和虚拟方法的真正目标是避免像您在.SuccessErrorvalidateReturnType.IsValid()IsValid()

于 2010-08-09T11:10:10.427 回答