《代码大全2》读书笔记——变量篇

来源:互联网 发布:python 自带shell 编辑:程序博客网 时间:2024/05/17 07:29

代码男孩

第十章 使用变量的一般注意事项

隐式变量申明

隐式变量申明是危险的,因为这可能导致错写了变量但却得不到提示。例如:

acctNum = 0...if acctNum < 0:    acctNm = 0...sqrt(acctNum)

变量的初始化

1、在靠近变量使用的位置申明和初始化变量。这样的好处有:第一,更容易找到变量的初始值。第二,减小了攻击窗口。

攻击窗口:介于同一个变量多个引用点之间的代码块。这段区域的代码可能修改该变量的值。

2、一次性初始化所有具名常量。在开头初始化所有具名常量,可以保证之后的代码中不会多次初始化该常量。

变量的作用域

变量的作用域是指变量的可见范围,循环下标的作用域是这个循环。全局变量的作用域是整个程序。

1、使变量的引用集中,缩短变量的存活时间(一个变量存在期间所跨越的语句总数)。如此不仅可以提高程序的可读性,同时减少了攻击窗口。一个坏的例子:

oldData = GetOldData()newData = GetNewData()PrintOldData(oldData)PrintNewData(newData)SaveOldData(oldData)SaveNewData(newData)

更好的解决办法:

oldData = GetOldData()PrintOldData(oldData)SaveOldData(oldData)newData = GetNewData()PrintNewData(newData)SaveNewData(newData)

这样杜绝了可能的相互影响,也让代码读起来更容易。

2、减少作用域的原则:
第一,在循环开始前的位置初始化循环中变量。一个例子:

dailySum = 0.........for i in range(1,10):    dailySum += GetDailyFee()

这时,如果我们要统计一周的总和:

dailySum = 0......weekSum = 0for j in range(1,8):    for i in range(1,10):        dailySum += GetDailyFee()    weekSum += dailySum

如果dailySum初始化的位置太远,就容易忘记在外层循环前初始化dailySum。

第二,变量使用前再为其赋值。赋值和使用的位置差距太远,可能就需要更多精力来确定该变量在第一次引用位置的值。

第三,相关语句放在一起。如上面 oldData, newData的例子所表示。

第四,相关语句提取为一个子程序。其他条件相同的情况下,提取相关语句为子程序可以获得更好的程序可读性和更小的变量存活时间。

3、方便性和智力上可管理性
作用域越大,变量方便性越高,可管理性越低。作用域越小,则相反。两者有时要根据情况进行取舍。

变量的持续性

持续性有多种形态:
1)for循环中申明的变量持续时间只有这段代码的生命周期
2)c++中,new创建的变量会持续到你delete它。
3)satatic变量会在程序整个生命周期持续。
4)永远持续,比如保存在数据库中的数据。

与持久性相关的最主要问题是变量实际的生命期比你想象的短。减少对变量持续保持的假设。可以使用以下方法避免上述问题:
1、在程序中使用断言和调试代码检查变量合理性。
2、抛弃变量时,给与变量不合理值。比如在删除一个指针指向的数据后,将该指针置为null。

变量绑定时间

变量绑定时间是指将变量赋予它应有的数值的时间。一般有以下几种绑定时间:
1、编码时:也就是所谓的硬编码。例:

titleBar.color = 0xff

2、编译时:申明具名常量,使用具名常量为变量赋值。例如:

COLOR_RED = 0xfftitleBar.color = COLOR_RED

3、运行时:从数据库中读取数据。如:

titleBar.color = GetTitleBarColor()

运行时绑定还分为:程序初始化时绑定;对象实例化时绑定;变量使用前绑定。

变量绑定时间越晚,程序灵活性越高,但是代码复杂度同样增加。实际中好的程序应该引入足够的灵活性来满足需求,但是又不添加过多不必要的灵活性以及相应的复杂度。

变量单一用途

1、不在多处程序使用同一个无意义的命名。例如:

temp = GetData()ProcessData(temp*temp).........temp = a[1]a[1] = a[0]a[0] = temp

这段代码中,上下两个temp没有任何关联。其实应该为变量赋予更有意义的名称。代码改进后如下:

data = GetData()ProcessData(data*data).........oldA = a[1]a[1] = a[0]a[0] = oldA

2、避免给变量添加隐含含义。例如pageCount代表纸张数量,同时使用-1代表程序遇到错误。这种情况下应该使用两个变量来表示这两个不同的含义。

第十一章 变量名的力量

命名以问题为导向

变量的命名应该以问题为导向而不是解决方案。变量名应该要描述这个量在问题中的语义。例如,一个程序的输入是员工信息,那么employeeData就比inputData好。inputData就是站在解决方案的角度思考的,描述了数据在程序中流动时所处的位置。简单说,要尽量减少计算机用语出现在变量名中。

变量名的长度

变量名长度在10-16个字符为宜。太少字符包含的信息不足,太多字符阅读不方便。

变量名表达作用域

1、将短的变量名代表作用域小的变量,那么阅读代码时就可以很容易通过变量名确定这个变量是不是个临时变量。
2、用前缀表示变量范围。例如,uiEmployee 表示用户界面的员工变量;dbEmployee表示数据库部分的员工变量。

使用限定词

如total, num, count, index, sum 等词语都是变量的限定词。
1、推荐将变量的限定词放在后面,这样使变量最基本的语义可以首先表达。
2、num的使用比较特殊,目前已经有了约定的习惯。num放在前面表示总数,num放在后面表示下标。

特定类型变量的命名

1、循环下标。
推荐给循环下标有意义的名称。一般循环下标 喜欢用i, j, k 这样的变量。但是这样的变量有以下问题:第一,循环长度过长时,变量的含义容易变得不清楚。第二,在多层循环中,容易写错下标。(把a[i][j]写成a[j][i])

2、状态变量。
同样要用有意义的名称,避免使用flag这样模糊的命名。好的命名应该像dataReady, characterType, reportType 这样。同时,结合具名常量一起使用效果最佳。如:characterType = CONTROL_CHARACTER。

3、临时变量
有意义的名称。不要用temp, x, y 等命名。

4、布尔变量
典型的命名:loadDone, studentFound, updateSuccess。布尔变量的命名要求能够有对应true和false的含义,比如loadDone = true 时很容易知道表示载入完成。

5、枚举类型
一个枚举类下的成员,使用同一个前缀,如:color_read, color_green。同时可以使用前缀e_表示枚举类型成员变量。

命名规则

命名规则的作用:第一,保证精力集中于全局的决策。第二,保证互相更快的学习对方代码。第三,可以提供编译器不提供的信息,比如一个TOTAL_NUM变量实际上被当做了一个常量使用。

何时需要使用命名规则:第一,多个程序员合作。第二,程序规模很大。第三,程序开发周期长,或者开发间隔了一段时间。

应当避免的命名

1、避免易产生误解的名字。例如用FALSE当做fig and almond season 的缩写。
2、避免混用具有相似含义的名字。例如 input, inputValue。这样使用容易时变量混淆。
3、避免含义不同却名字相似的变量:clientRecs, clientReps。两个名称只差了一个字母。
4、避免仅靠大小写来区分变量。

0 0
原创粉丝点击