我想在这里提到两点。
第一是测试,第二是性能问题。
1)测试
你提到测试可以做很多事情,而且测试是确保代码正确的唯一方法。总的来说,我认为这是绝对正确的。但是测试本身只解决了一个问题。
如果您编写一个模块,那么您有两个问题或者说有两个不同的人使用您的模块。
您作为开发人员和使用您的模块的用户。测试有助于第一个问题,即确保您的模块正确并执行正确的操作,但它并没有帮助只是使用您的模块的用户。
对于后者,我有一个例子。我使用Moose和其他一些东西编写了一个模块,我的代码总是出现段错误。然后我开始调试代码并寻找问题。我花费了大约4个小时的时间来查找错误。最后问题是我使用了具有Array Trait的Moose。我使用了“map”函数,但我没有提供子例程函数,只是一个字符串或其他内容。
当然,这是我的绝对愚蠢的错误,但我花费了很长时间来调试它。最后,仅仅检查输入参数是否为subref将使开发人员花费10秒钟的时间,并且会让我和可能其他人花费更多的时间。
我还知道其他例子。我已经完全使用Moose编写了REST客户端接口。最后,您总是会得到对象,您可以更改属性,但是它不会为每个更改调用REST API。相反,您更改值,最后调用update()方法传输数据并更改值。
现在我有一个用户写道:
$obj->update({ foo => 'bar' })
当然,我得到了一个错误,即update()不起作用。但是它确实没有起作用,因为update()方法没有接受hashref。它只是将对象的实际状态与在线服务同步。正确的代码应该是。
$obj->foo('bar');
$obj->update();
第一件事有效,因为我从未检查过参数。如果有人给出比我期望的更多的参数,我不会抛出错误。该方法就像正常一样开始。
sub update {
my ( $self ) = @_;
...
}
当然,我的所有测试都绝对100%正常工作。但是处理这些不是错误的错误也花费了我的时间。它也会让用户花费更多的时间。
所以最后。是的,测试是确保您的代码正确运行的唯一正确方法。但这并不意味着类型检查是毫无意义的。类型检查是为了帮助您模块上的所有非开发人员正确使用您的模块。并节省您和其他人找到垃圾错误的时间。
2) 性能
简单来说:在你关心之前,性能并不重要。
这意味着在你的模块工作得太慢之前,性能总是足够快的,你不需要关心它。如果你的模块真的运行得太慢,你需要进行进一步的调查。但是为了这些调查,你应该使用像 Devel::NYTProf 这样的分析器来查看哪里出现了问题。
我会说,在99%的情况下,慢并不是因为你进行类型检查,而更多的是因为你的算法。你进行了很多计算,过于频繁地调用函数等等。通常,如果你使用完全不同的解决方案、使用更好的算法或者进行缓存等操作,性能就会得到提升,而不是因为你进行了类型检查。但是即使检查是导致性能问题的原因,那么就只在需要的地方删除它。
没有理由在不需要关心性能的地方进行类型检查。比如,你觉得在上面的例子中进行类型检查很有必要吗?在这里,我编写了一个 REST 客户端。99% 的性能问题都是请求发送到 Web 服务的次数或者请求所需的时间。不使用类型检查或者 MooseX::Declare 等东西可能根本不会加快速度。
即使你看到了性能上的劣势,有时候也是可以接受的。因为速度并不重要,或者因为某些东西给你带来了更大的价值。DBIx::Class 比使用 DBI 的纯 SQL 更慢,但是 DBIx::Class 为你提供了很多好处。