我应该重用变量吗?
我知道许多最佳实践表明您不应该这样做,但是,稍后,当不同的开发人员调试代码并具有3个看起来相似的变量时,唯一的区别是它们是在代码中的不同位置创建的,困惑。单元测试就是一个很好的例子。
但是,我确实知道,最佳实践通常都是反对的。例如,他们说不要“覆盖”方法参数。
最佳做法甚至是反对使以前的变量为空(在Java中,Sonar会在您分配null
给变量时发出警告,因为Java 6不需要调用它来调用垃圾回收器。您无法始终控制哪些警告已关闭;大多数情况下默认设置为开启。)
我应该重用变量吗?
我知道许多最佳实践表明您不应该这样做,但是,稍后,当不同的开发人员调试代码并具有3个看起来相似的变量时,唯一的区别是它们是在代码中的不同位置创建的,困惑。单元测试就是一个很好的例子。
但是,我确实知道,最佳实践通常都是反对的。例如,他们说不要“覆盖”方法参数。
最佳做法甚至是反对使以前的变量为空(在Java中,Sonar会在您分配null
给变量时发出警告,因为Java 6不需要调用它来调用垃圾回收器。您无法始终控制哪些警告已关闭;大多数情况下默认设置为开启。)
Answers:
仅当您的方法很长并且按顺序执行多个任务时,才会出现问题。这使得代码本身很难理解(并因此得以维护)。重用变量还增加了额外的风险,使代码更难遵循且更容易出错。
IMO的最佳做法是使用足够短的方法仅做一件事,从而消除整个问题。
result1 = foo(); result2 = foo(); Assert.AreEqual(result1, result2);
在这种情况下,我看不到很多地方需要重用变量。
方法中的变量重用是您应该重构/拆分它的强烈标志。
因此,我的回答是您不应该重用它们,因为如果这样做,那么以后对其进行重构将变得更加困难。
这取决于。
可能正是出于保存某种数据的目的而创建了一些变量,这些数据在函数执行期间可能会发生变化。这里想到了返回码,例如:
void my_function() {
HRESULT errorcode;
errorcode = ::SomeWindowsApiFunction();
if (FAILED(errorcode)) { /* handle error */ }
errorcode = ::AnotherWindowsApiFunction();
if (FAILED(errorcode)) { /* handle error */ }
}
变量名称可以很清楚地表明此变量打算存储什么。我认为诸如此类的其他用例也是可能的,其中变量在概念上是一个容器,在功能过程中,该容器在逻辑上由非常相似的事物的不同实例使用。
但是,通常,只有在可能的代码阅读者绝对清楚的情况下,才应这样做。在任何情况下,除了可能不考虑代码易读性的极端优化之外,都不应仅仅因为类型合适而重用变量。
所有这些基本上都源于变量命名的良好实践。名称应该说明一切。如果很难将所有重复使用的确切目的简称为短名称,则最好仅使用不同的变量。
我不重用变量的最大原因(尤其是在单元测试中)是因为它引入了不必要的代码路径,这是很难测试和调试的。好的单元测试应该独立于其他测试,并且在单元测试夹具中重用类(实例)级别变量时,必须确保在每次测试之前声明其状态。好的单元测试还可以隔离缺陷,因此从理论上讲,每个测试用例(方法)应仅针对被测系统断言1种行为。如果您的测试方法是这样编写的,则很少或不需要重用方法级别的变量。最后,在支持闭包和异步处理的语言中,如果要在整个方法中重用变量,则很难推断到底发生了什么。
在任何情况下,无论其他答案给出了什么好建议,您都可能希望重用变量:当编译器需要帮助时。
在某些情况下,您的编译器可能不够聪明,以至于无法意识到代码的下一部分不再使用某个寄存器分配的变量。因此,它将不会在理论上免费使用下一个变量的寄存器,并且生成的代码可能不是最佳的。
请注意,我不知道任何当前的主流编译器都无法正确捕捉这种情况,因此,除非您知道编译器正在生成次优代码,否则永远不要这样做。如果要使用自定义编译器为特殊的嵌入式系统进行编译,则可能仍会遇到此问题。
这取决于。在动态语言中,类型驻留在值而不是变量上,那么如果我对一个函数(例如,是一个字符串)有一个命名良好的参数,我对算法进行了更改,这意味着它总是在被解释为整数后才使用,然后,作为初稿,我可能会做
scrote = int(scrote)
但是我最终希望更改发送给函数的类型,并注意参数类型的更改。
首先,查看您的开发环境。如果由于在不同作用域中具有五个具有相同名称的变量而在调试过程中遇到问题,并且调试器没有向您显示这些变量中的哪个是您需要的,那么不要使用五个具有相同名称的变量。有两种方法可以实现:使用一个变量,或使用五个不同的名称。
您的调试器也可能使调试具有多个变量的函数变得很痛苦。如果具有20个变量的功能比具有16个变量的功能更难调试,则您可以考虑将5个变量替换为1个。(“可能考虑”与“应该始终”不同))。
只要该变量始终具有相同的用途,就可以在多个位置使用一个变量。例如,如果十个函数调用返回一个错误代码,并且每次调用都会立即处理该错误代码,则使用一个变量而不是10。但是对于完全不同的事物,请勿使用相同的变量。就像使用“名称”作为客户名称,然后在10行之后使用相同的变量作为公司名称一样,这很糟糕,并且会给您带来麻烦。更糟糕的是,使用“ customerName”作为客户名称,然后在10行中使用相同的变量“ customerName”作为公司名称。
重要的是,没有什么是铁律。一切都有优点和缺点。如果“最佳做法”暗示一件事,而您却有理由说这在您的特定情况下不是一个好主意,那么就不要这样做。
首先,查看您的开发环境。如果由于在不同作用域中具有五个具有相同名称的变量而在调试过程中遇到问题,并且调试器没有向您显示这些变量中的哪个是您需要的,那么不要使用五个具有相同名称的变量。有两种方法可以实现:使用一个变量,或使用五个不同的名称。
您的调试器也可能使调试具有多个变量的函数变得很痛苦。如果具有20个变量的功能比具有16个变量的功能更难调试,则您可以考虑将5个变量替换为1个。(“可能考虑”与“应该始终”不同))。
只要该变量始终具有相同的用途,就可以在多个位置使用一个变量。例如,如果十个函数调用返回一个错误代码,并且每次调用都会立即处理该错误代码,请使用一个变量而不是10。这有一个问题:通常,编译器会在您使用未初始化的变量时告诉您。但是在这里,如果您在调用6之后读取了错误代码,但是在调用5之后实际上并未更改该变量,则在没有编译器警告的情况下,您将获得无用的数据。因为变量已经初始化,所以现在没有数据。
重要的是,没有什么是铁律。一切都有优点和缺点。如果“最佳做法”暗示一件事,而您却有理由说这在您的特定情况下不是一个好主意,那么就不要这样做。