静态方法的函数式编程建议如何影响可测试性?

时间:2011-11-29 09:32:40

标签: c# unit-testing functional-programming

我越是深入研究函数式编程,我读到了支持静态方法的建议,转而采用非静态方法。您可以在本书中阅读该建议,例如:

http://www.amazon.de/Functional-Programming-Techniques-Projects-Programmer/dp/0470744588

当然,如果你考虑功能纯度,这是有道理的。一个静态函数站在那里说:"我不需要任何状态!"

然而,这对可测试性有何影响?我的意思是,具有大量静态方法的系统难以测试(因为静态方法难以模拟)?或者模拟在函数式编程中扮演次要角色,如果是这样的话:为什么?

修改

因为怀疑这本书是否真的提出了这个建议。我会再引用一点。我希望Oliver Sturm没问题。

使用静态方法

  

静态方法是一般值得考虑的基本思路之一。许多面向对象的程序员都支持它,从功能的角度来看,函数可以在大多数时候保持静态。任何纯函数都可以是静态的。   (...)

     

有些人可能会争辩说,总是传递所有参数的想法意味着你并没有尽可能多地利用面向对象的想法。事实上这可能是真的,但也许是因为面向对象的概念并没有像他们应该那样多地考虑并行执行的问题。   (...)

     

最后,建议的指南:当你编写了一个不需要访问它所在类中任何字段的方法时,将其设置为静态!

到目前为止,有很好的答案。谢谢你!

4 个答案:

答案 0 :(得分:11)

一种看待这种情况的方法是,对于函数式编程,您只需要模拟特定函数所需的状态(通过提供合适的输入)。对于OO编程,您需要模拟该类内部工作所需的所有状态。

功能程序还有一个附带的好处,即您可以保证使用相同的输入重复相同的测试将得到相同的结果。在经典的OO中,你必须保证不仅仅是相同的输入,而是相同的整体状态。

在架构良好的OO代码中,差异将是最小的(因为类将具有明确定义的责任),但功能测试的要求仍然是等效OO测试的严格子集。

(我意识到函数式编程风格可以通过不可变对象使用OO - 请将上面提到的OO读作'具有可恢复状态的面向对象编程')

编辑:

正如Fredrik所指出的,关于功能方法的重要部分并不是它们是静态的,而是它们不会改变程序的状态。 “纯”函数是从一组输入到一组输出的映射(相同的输入总是给出相同的结果),并且没有其他影响。

答案 1 :(得分:5)

纯函数式编程中的所有“状态”都来自输入。要对功能程序进行单元测试,您可以创建测试输入并观察输出。如果无法通过给出测试输入并观察输出来测试您的方法,则它们的功能不够。

答案 2 :(得分:4)

我认为静态方法本身不是问题,当他们开始对静态数据进行操作时会出现问题。只要静态方法将输入作为参数,对其进行操作并返回结果,我发现测试它们没有问题。

即使我没有在我的代码中使用函数方法,我倾向于在可能的情况下使方法保持静态。但在引入静态或静态类型之前,我认为非常小心

答案 3 :(得分:2)

在函数式编程中,您需要模拟函数而不是对象。因此,如果您想测试函数f而不依赖于

中的某些ComplicatedAndLongFunction
f(x)
{
    myx = g(x);
    y = ComplicatedAndLongFunction(myx);
    myy = h(y)
    return myy;
}

您可能希望将fComplicatedAndLongFunction分开,将后者注入f:

f(x, calc)
{
    myx = g(x);
    y = calc(myx);
    myy = h(y)
    return myy;
}

因此您可以在测试中指定calc的行为。

这提出了一个问题(至少在我看来),如果有模拟框架可以很容易地指定对函数的期望而不必回复到对象。