第十章, 使用变量的一般事项
前言
利用构建活动来填补需求和架构中存在的细小间隙是一种行之有效的做法,但把蓝图设计得精细到已经能完全展现出所有的细节则实在是一种低效的做法。
10.1 数据认知
创建数据的第一步是了解所要创建的数据的种类。
10.2 轻松掌握变量定义
隐式声明:
是指你在使用一个未定义的变量的时候,编译器会自动为你声明此变量。隐式变量声明对任何一种语言来说都是最具危险的特性之一。
避免的方法:
1、 关闭隐式声明。
2、 声明全部的变量,对PHP来说最好是赋初始值。
3、 遵循某种命名规则。
4、 检查变量名。
10.3 变量初始化原则
1、 在声明变量的时候初始化。
2、 遵循就近原则(Principle of Proximity),在靠近变量第一次使用的位置初始化它。
3、 在理想情况下,在靠近第一次使用变量的位置声明和定义该变量。
4、 在可能的情况下,使用final和const。final是java中类似于C++里const的关键字。
5、 特别注意计时器和累加器。在使用计数器和累加器时最好初始化或重置。
6、 在类的构造函数里初始化类的数据成员。
7、 检查是否需要重新初始化。特别是循环中的变量。
8、 一次性初始化具名常量;用可执行代码来初始化变量。
9、 使用编译器设置来自动初始化所有变量。
10、 利用编译器的敬重信息。
11、 检查输入参数合法性。
12、 使用内存访问检查工具来检查错误的指针。
11、 在程序开始时初始化工作内存。
10.4 作用域
作用域或者可见性是指变量在程序内的可见和可引用的范围。
使变量应用局部化:
介于同一个变量多个引用点之间的代码可成为“攻击窗口”。可能会有新代码加到这种窗口中,不断的修改了这个变量,或者阅读代码的人可能会忘记该变量有的值。一般而言,把对一个变量的引用局部化,即把引用点尽可能集中在一起总是一种很好的做法。主要的好处是提高程序的可读性和可维护性。
可以用跨度来衡量:引用间相隔的代码行数。
尽可能的缩短变量的存活时间:
一个变量存在期间所跨越的语句总数。跨度表明变量引用的集中程度,存活时间表明变量经历的语句。
低存活时间的好处是减小攻击窗口,使你对代码有更准确的认识(提高可读性),减少初始化错误。
最后,一个明显的好处是便于程序重构,如果一个程序拆分为多个小的程序,短的存活时间更有价值。
用跨度和生存时间来考察全局变量,会发现全局变量跨度和生存时间都很长——这是避免使用全局变量的好的理由之一。
减小作用域的一般原则:
1、 在循环开始之前再去初始化改循环里使用的循环变量,而不是在该循环所属的子程序的开始处初始化这些变量。
2、 直到变量即将被使用时再为其赋值。把声明和定义放在使用之前。
3、 把相关语句放在一起。减少变量的跨度和生存时间。
4、 把相关的语句组提取成功单独的子程序。把一个长的子程序拆分为更小的、单独的子程序可以缩小变量的作用域。
5、 开始时采用最严格的可见性,然后根据需要扩展变量的作用域。当对变量作用域犹豫不决时,应该倾向于选择该变量所能具有的最小的作用域:首先将变量限制于某个特定的循环,然后是局限于某个子程序,其次是类的private变量,protected变量,再其次对包可见,最后不得已的情况下再把它作为全局变量。
关于对变量作用域的态度,取决于程序员如何看待“方便性”和“智力上的可管理性”。作用域越大,在写代码时越方便。但是写出的程序更难于理解、阅读、调试和维护。
10.5 持续性
持续性是对数据项的生命周期的另一种描述。
1、 特定代码段或子程序生命周期。
2、 动态申请。
3、 程序生命周期。
4、 永久生存。
为了防止变量已经消失,可以:
1、 程序中加入调试或断言来判断。
2、 在抛弃它的时候,给他附上不合理的值。
3、 编写代码的时候假设变量没有持续性。
4、 养成在使用所有时间之前都声明和初始化的习惯。
10.6 绑定时间
绑定时间:把变量和它的值绑定在一起的时间。
一般而言,绑定的时间越晚,灵活性越高,复杂度越大。
硬编码。
编译时,
加载时。
对象实例化时。
即时。
10.7 数据类型和控制结构之间的关系
1、 序列型数据翻译为程序中的顺序语句。
2、 选择型数据翻译为程序中的if和else语句。
3、 迭代型数据翻译为程序中的for,while,等循环结构。
10.8 为变量指定单一用途
1、 每个变量只用于单一用途。
2、 避免让代码具有隐含意义。当其代表不同事物时,具有不同的取值集合。我用过一些,用一个值的大小范围表示不同的含义。这种滥用在技术领域里称为混合耦合。
3、 确保使用了所有的变量。
CHECKLIST: General Considerations In Using Data 核对表:使用数据的一般注意事项 初始化变量 1、 每一个子程序都检查其输入参数的有效性吗? 2、 变量声明位置靠近变量第一次使用的位置吗? 3、 尽可能在声明变量的时候初始化变量吗? 4、 如果无法同时声明和初始化变量,有没有在靠近第一次使用变量的位置声明变量? 5、 计数器和累加器经过了适当的初始化了吗?如果需要再一次使用,之前重新初始化了吗? 6、 适当的重新初始化“需要重复执行的代码里的变量”了吗? 7、 代码在经过编译器编译时是不是没有告警?(你启用了所有的告警选项了吗?) 8、 如果你所使用的语言允许隐式声明,你为此可能引起的问题做好补偿措施了吗? 使用数据的其他事项 1、 如果可能,所有的变量都被定义为具有最小的作用域吗? 2、 各变量的引用点都尽可能的集中在一起吗?对同一个变量的两次相邻引用,或者整个变量的生命周期都这样做了吗? 3、 控制结构符合数据类型吗? 4、 所有声明的变量都用到了吗? 5、 变量都在合适的时间绑定了吗?——也就是所,你有意识的在晚期绑定所带来的灵活性和增加的复杂度之间做出平衡了吗? 6、 每个变量有且仅有一项用途吗? 7、 每个变量的含义都很明确且没有隐含意义吗? |
本章要点
1、 数据初始化很容易出错,使用本章所描述的初始化原则。
2、 最小化每个变量的作用域。把同一个变量的引用点集中在一起。把变量限定在子程序或类的范围内。避免使用全局变量。
3、 把使用相同变量的语句尽可能的集中在一起。
4、 早期绑定数据会降低灵活性,但有助于减小复杂度。晚期绑定可以增加灵活性,但同时又增加复杂度。
5、 把每个变量用于唯一的用途。