让我们看看如何通过最小化变量的可见性来防止意大利面条代码现象的一些建议。
我们的目标是尽可能减少变量在源代码中可见的代码部分,即减少变量的范围。
范围最小化是一种结构化代码的过程,它很容易:
- 声明具有最小范围的变量,并且
- 为变量分配具有最小范围的数据。
事实上,定义变量可见性的是代码结构。
背景概念
程序由简单(例如赋值)或复合(例如条件、循环)语句的组合组成。
后一种语句可以嵌套,这意味着它们可以由可以包含其他语句的代码块组成。
特别是,让我们考虑两个块A和B:
- 如果A包含B ,我们说A是B的外部块,而
- 如果B包含在A中,我们说B是A的内部块。
块的缩进级别是其嵌套级别的数量,并且对应于比其外部块高一级。
让我们将全局范围定义为没有外部块和缩进级别 0 的特殊块。
最后,全局变量是在全局范围内定义的变量。
可变可见性规则
在以下代码部分中可以看到一个变量:
- 从变量的声明语句开始,
- 在变量声明块的末尾结束,并且
- 包括1. 和 2 中的所有嵌套块。
作为补充,变量在以下代码部分中不可见:
- 在变量的声明之前,和
- 在变量的声明块结束之后。
建议
- R1。永远不要使用全局变量
- R2。声明单一用途变量
- R3。声明接近其用途的变量
- R4。保持代码块小
- R5。使用接近其声明的变量
- R6。使用不超过两个嵌套级别
R1。永远不要使用全局变量
永远不要声明或使用全局变量,因为它们会使代码更难阅读、维护和测试。请参阅“全局变量不好”。
它们的使用增加了有问题的副作用的发生,这通常会导致难以识别和修复的编程错误。
程序中可能错误分配变量的语句越少越好。
总之,使用全局变量往往代表技术债务,必须尽快通过代码重写来偿还!
R2。声明单一用途变量
为单一特定目的声明和使用变量,以便将它们的范围限制在最低限度。
声明变量的用途越多,变量可见的语句数量就越多。
变量可见的语句数量越多,可能错误地分配变量的语句就越多。
可能错误地分配变量的语句越多,就越难发现和修复潜在的错误。
总结:只声明和使用单一用途的变量。
R3。声明接近其用途的变量
将变量声明为尽可能接近将使用它们的语句和代码块。
与建议 R2 严格相关,这是减少可以使用已声明变量的语句数量的另一种方法。
示例:三个后续块
首先,让我们考虑三个后续代码块A、B和C,即:
- A、B和C位于同一个外部块中,并且
- 它们具有相同的缩进级别。
其次,让我们在 A之前立即声明一个变量v ,与A的缩进级别相同。
根据可见性规则,v将对所有三个后续块A、B和C可见。
现在让我们假设我们需要v只对C可见。
显然,在C之前立即声明v将通过使其仅对C中的语句可见而降低其可见性。到目前为止,一切都很好!
但是,如果在没有遵循下一个建议的情况下遵循此建议,则仅部分有用。
R4。保持代码块小
与关于单一用途变量的建议 R2 类似,通过使代码块专注于单个特定任务来保持代码块尽可能小。
否则,专用于不同任务的代码块部分可能会不必要地看到某些变量。
让我们再看一下前面介绍的三个后续块A、B和C,它们具有相同的缩进级别。
假设我们需要声明一个变量w供A使用和修改,而只被 B 和 C 读取。
在 A 之前立即声明w是不可避免的,因此它的范围将不必要地包括B和C。
这使得B和C也可以分配w,同时希望它们只能读取w的值。
我们如何避免这种情况?只需将B和C分成两个不同的函数,将w作为参数之一。
总结:让代码块成为单任务,将子任务移动到单独的函数中。
R5。使用接近其声明的变量
请记住使用尽可能接近其声明的变量。
假设您需要使用(即读取或分配)在外部块中声明的变量v 。
请记住尽量减少使用v的语句和v的声明块之间的缩进级别。
一般规则:变量声明及其使用之间的最大嵌套级别数应为2 。
为了完整起见,让我们看一个示例,在该示例中,在三个嵌套级别(即比推荐的多一级)处使用变量可能是合理的。
示例:矩阵乘法算法
让我们考虑使用三个嵌套循环的迭代矩阵乘法算法。
最深的此类循环包含以下赋值语句:
sum ← sum + A ik × B kj。
语句使用的A和B在距离的三个嵌套级别的外部块中声明,这比建议的最大值多一级。
在这种情况下,对规则做出例外处理是非常可以原谅的。
除了极端情况外,在使用外部块中声明的变量时,考虑到三个太多的缩进级别。
尽管建议 R6 实际上可以满足,但在组织代码时牢记此建议始终是一个好主意。
R6。使用不超过两个嵌套级别
一般来说,记得尽可能减少嵌套块的深度。
每个函数中的最大嵌套深度最多应为两个。
当函数的嵌套深度大于 2 时,请按以下方式对其进行重构:
- 将一些子块移动到单独的功能中,以及
- 将移动的子块使用的变量作为函数的参数传递。
如建议 R5 中所见,有时将三个作为最大深度是合理的。
同样,除了极端情况外,始终将两个视为最大嵌套深度。