在我看来,我被迫要么编写我可以测试的代码,但不利用接口的语言支持,或者使用语言支持,但在测试中遇到困难。
为什么需要访问private
变量和函数?它们要么在某些时候被public
函数调用(但间接地),要么它们只是不可访问的代码片段,根本不应该存在,因为无法调用它们。想一想,如果完全private
不可能从类外部以任何方式调用该方法,它会被运行吗?
如果你真的想测试一个private
方法,你可以把它拉到它自己的类中。另外,如果它非常复杂以至于它真的需要最好地单独测试,那么它就有机会首先得到它的机会。另一种选择是在您需要/想要测试它时将其公开,但实际上并不更改“真实”代码(保留它private
)。正如其他人所说,某些语言还具有通过稍微公开它们来帮助您测试这些方法的功能,例如 C++ 中的朋友、C # 中的内部和Java 中的包私有。 有时 IDE 自己甚至会提供帮助。
是否有任何充分的理由发出错误而不是警告?
一个很大的原因不是你不能打电话给他们,而是其他人不能打电话给他们。想象一下,您正在编写一个将被大量客户使用的库。您已经标记了他们不需要调用的所有内容private
,并且他们需要的所有功能都是公开的。程序员继续使用您的库,用它编写一堆代码,并从他们自己和他们自己的客户中产生满意的客户。
几个月后,您决定为您非常成功的库增添趣味,并发现您需要进行一些重构。因此,您 [重命名、添加/删除参数、删除] 一些private
方法,但要小心保持所有公共方法的接口完全相同,以使升级过程无缝。但是在这个世界中,编译器只在您访问变量时发出警告而不是错误private
,并且您的一些客户端程序员编写了调用这些private
方法的代码。现在,当他们尝试升级到您的库的新版本时,他们会遇到一堆真正的错误,因为他们无法调用这些错误private
方法了。现在他们要么必须花时间找出代码出了什么问题,要么重写他们不记得的大部分代码(我是否提到这是两年后的事?)。因此,他们必须完全重新学习如何使用您的库并重写他们的客户端代码,这对任何人来说都不是一件有趣的事情。现在他们很不高兴,因为你如此不体谅你,以至于你的升级真的破坏了他们所有的代码,让他们的生活变得更加困难。
猜猜看,当他们修复代码时,他们研究并调用了您的新private
方法,因此如果您决定在发布升级时更改他们的界面,整个循环将重新开始。对你来说稍微方便一点的只是让你有一群不满意的客户。
等等,他们不是白痴调用我的私有方法吗?他们为什么不看警告?这是他们的错,不是我的!
嗯,是的,这是他们的错,他们本可以通过注意这些警告来防止问题的发生。但并不是每个人都是想要修复和理解警告的代码质量狂热者,而且相当多的人只是忽略了它们。问题是,如果编译器发出错误以尝试访问变量和方法而不是警告,那么您可以自己阻止整个事情private
,因为否则private
关键字可能根本不存在。您可能已经失去了一点时间,因为这些方法更难测试,但您已经获得了阻止不聪明的人滥用您的代码并将导致他们在路上出现的任何问题归咎于您的能力。
我最喜欢的软件开发(以及一般的产品设计)的原则之一是事情应该易于正确使用,并且很难或不可能不正确地使用。真正的私有成员就是这个建议的体现,因为它们确实使您的代码无法正确使用。
[假设性反驳:]好吧,使用我的代码的人应该足够聪明,可以弄清楚。我只要求他们多花一点时间来正确使用代码。
所以你有意识地拒绝花必要的时间来提高你的代码质量,让它更容易使用?然后我不想与你的代码有任何关系。显然,您的时间比您的客户的时间更重要,因此我将花费 2.5 秒来关闭您的项目的网页并单击下一个 Google 结果。您使用的库成员比您想象的要多得多private
,而光荣的事情是您不必花费一毫秒的时间来担心它们,因为它们对您完全隐藏并且只会分散注意力从提供的更简单和更好的做事方式public
界面。如果所有内容都是公开的或发出微弱警告的私有内容,那么在真正找到所需内容之前,您必须筛选更多功能。
每当您private
在成员函数之前键入时,您就已经赋予自己在未来任何时候以您想要的任何方式更改它的权力,因为除了您之外没有人可以触摸它。第二次其他人尝试访问它时,他们将收到一个显示停止错误,因为编译器支持你,并且当你已经以更可用的形式完美地提供了他们需要的一切时,他们不会让他们对你的代码做任何愚蠢的事情在您的public
界面中。
是的,它会让现在的测试变得稍微困难一些,但它也确保了你将来在重构时不必担心它,并使你的代码更容易被其他人使用。继续并暂时将其公开(我有点喜欢您的“全公开编译器切换”想法 :),但是当您完成后不要忘记将其切换回来,您和您的客户都可以享受使用更简单和更简单的工作的乐趣更具适应性的代码。:D