流畅的接口应该提高可读性,但我有一个怀疑,有一个长的LOC,包含很多链式方法。
有任何编译器的问题吗?
有任何调试问题吗?
有任何运行时/错误处理问题吗?
流畅接口用于例如。 TStringBuilder,THTMLWriter和TGpFluentXMLBuilder。
更新:
David Heffernan问我关注哪些问题。我已经给了这个想法,总体问题是“明确指定如何做”和“让编译器决定如何做”之间的区别。
AFAICS,没有关于如何链接方法实际上由编译器处理的文档,也没有关于编译器如何处理链接方法的任何规范。
在this article中,我们可以看到编译器如何为声明为函数的方法添加两个额外的var参数,而标准调用约定将三个参数放入寄存器,将下一个放在堆栈中。具有2个参数的“流利函数方法”将使用堆栈,而具有2个参数的“普通过程方法”仅使用寄存器。
我们还知道编译器做一些魔术来优化二进制(例如string as function result,evaluation order,ref to local proc),但有时对程序员有令人惊讶的副作用。
所以事实上,内存/堆栈/寄存器管理更复杂,事实,编译器可以做一些魔法与无意的副作用,对我来说很臭。因此问题。
在我读了答案(非常好的),我的关注大大减少,但我的喜好仍然是相同:)
解决方法
如果你使用的是接口(而不是对象),链中的每次调用都会导致引用计数开销,即使完全相同的接口一直返回,编译器也无法知道它。因此,您将生成一个更大的代码,使用更复杂的堆栈。
调试问题:
调用链被视为单个指令,您不能在中间步骤上执行步骤或断点。您也不能在中间步骤评估状态。
调试中间步骤的唯一方法是在asm视图中进行跟踪。
调试器中的调用栈也将不清楚,如果相同的方法在流畅链中发生多次。
运行时问题:
当为链(而不是对象)使用接口时,您必须支付引用计数开销,以及更复杂的异常框架。
你不能有try..finally在链中构造,所以不能保证关闭在流畅链f.i中打开的东西。
调试/错误日志问题:
异常和它们的堆栈跟踪将链看作一个单独的指令,所以如果你在.DoSomething中崩溃,并且调用链有几个.DoSomething调用,你不知道是什么引起的问题。
代码格式问题:
AFAICT没有一个现有的代码格式化程序将正确地布局一个流利的调用链,所以它只有手动格式化,可以保持流畅的调用链可读。如果运行自动格式化程序,它通常会将链变成可读性混乱。