一、使用变量的一般事项

1.把变量引用局部化

变量应用局部化就是把变量的引用点尽可能集中在一起,这样做的目的是增加代码的可读性

衡量不同引用点靠近程度的一种方法是计算该变量的跨度(span)



示例

a = 0
b = 0
c = 0
a = b + c

a的第一次引用和第二次引用之间存在两行代码,因此变量的跨度是2,b的第一次引用和第二次引用之间存在一行代码,因此跨度是1。

平均跨度可以通过计算各个跨度的平均值得到。来看一个示例

a = 0
b = 0
c = 0
b = a + 1
b = b / c

b的第一次引用和第二次引用的跨度为1,第二次引用和第三次引用的跨度为0,因此平均跨度为(1 + 0) / 2 = 0.5。当把变量的引用点集中在一起的时候,阅读者能每次只关注一部分代码,如果这些引用点之间的距离非常远,那里就要迫使阅读者的目光在程序里跳来跳去


#### 2.尽可能缩短变量的存活时间

存活时间是指一个变量存在期间所跨越的语句总数。变量的存活时间开始于引用它的第一条语句,结束于引用它的最后一条语句。

注意:存活时间只关注第一次引用和最后一次引用,而不关注中间有多少次引用。长存活时间意味着一个变量历经了许多条语句,而短存活时间意味着它只历经很少的语句,跨度表明对一个变量引用的集中程度

保持较低的存活时间的好处在于能够减小攻击窗口,因为存活时间短,该变量被错误或无意修改的可能性就变小了

小结

跨度:变量两次引用之间相隔的代码行数

减小跨度的好处:增强代码的可读性

存活时间:变量第一次引用和最后一次引用之间的代码行数

减小存活时间的好处:减小攻击窗口、增强可读性、方便重构

3.减小作用域的一般原则

1)在循环开始之前再去初始化该循环里使用的变量,而不是在该循环所属的子程序的开始处初始化这些变量

2)直到变量即将被使用时再为其赋值,让变量的赋值位置越明显越好

3)拆分,把使用了类似的变量的语句放在一起

4)开始时使作用域尽可能小,之后有需要时再扩充

4.绑定时间

变量和它的值绑定在一起的时间称为绑定时间。这一绑定是在编写代码的时候还是编译程序的时候,是在程序加载的时候还是运行的时候?

采用越晚的绑定时间越有利,绑定时间定义的越晚,代码就包含越多的灵活性。下面来看几个例子

1)在编写代码的时候绑定值

java示例

titleBar.color = 0xFF;	//0xFF is hex value of color blue

这是典型的硬编码,这种硬编码技术通常是很糟糕的,因为一旦要修改这个值,那么这个新值就无法同代码中其他引用的地方保持一致了。要杜绝这种使用方式。

2)在编译时绑定值

java示例

private static final int COLOR_BLUE = 0xFF;
private static final int TITLE_BAR_COLOR = CLOR_BLUE;
...
titleBar.color = TITLE_BAR_COLOR

TITLE_BAR_COLOR是一个具名常量,编译器会在编译的时候把它替换为一个数值,这种方式有两个好处:

a. 易于修改,一处修改就能对所有位置生效

b. 可读性更强

补充:

private是java的关键字,可以用来修饰成员变量和成员方法,被其修饰的成员只能在本类中访问

static也是关键字,用static声明的成员变量为静态成员变量,也称为类变量,类变量的生命周期和类相同,在整个应用程序执行期间都有效。

final也是关键字,可以用来修饰引用、方法和类。如果引用为基本数据类型,则该引用为常量,该值无法修改;如果引用为引用数据类型,如对象、数组,则该对象数组本身可以修改,但指向该对象或数组的地址的引用不能修改

final修饰方法时,被修饰的方法将称为最终方法,无法被子类重写,但是,该方法仍然可以被继承

final修饰类时,该类成为最终类,无法被继承,简称为断子绝孙类。

对于Python这类解释型语言,可以这样绑定

COLOR_BLUE = 0xFF	# 这里可以直接写在代码里或者写在配置文件里
titleBar.color = TITLE_BAR_COLOR

3)在运行时绑定值

java示例

titleBar.color = ReadTitleBarColor();

使用一个子程序在程序运行期间读入数值的子程序,数值来源可能注册表或者配置文件

#### 小结

绑定时间的有以下几种

1)编码时,也就是硬编码,应杜绝这种情况

2)编译时,使用具名常量,推荐这种方式

3)加载时,从外部数据源读取数据,推荐这种方式

5.数据类型和控制结构之间的关系

1)序列型数据翻译为程序中的顺序语句

2)选择型数据翻译为程序中的if和case语句

3)迭代型数据翻译为程序中的for、while等循环结构

6.为变量指定单一用途

1)每个变量只用于一个用途

常见的就是使用毫无意义的temp临时变量,不同地方的temp实际上毫无关联,但是却共用一个变量,这样会使得本无关联的两者看上去似乎彼此关联,从而降低了可读性

2)避免让代码具有隐含意义

把同一变量用与多个用途的另外一种方式是当变量代表不同事物时让其具有不同的取值集合。举个栗子:

  • 变量pageCount的取值表示已打印的纸张的数量,当它等于-1时,表示有错误发生

  • 变量customerId代表某个客户账号,当它的取值大于50000时,你可以通过减去50000来得到过期账户的号码

  • 变量byteWritten表示输出文件的字节数,如果取值为负,表示用与输出的磁盘驱动器的号码

应该避免使用这种具有隐含意义的变量。这种滥用在技术领域称为“混合耦合”,第一个例子里pageCount表示纸张数量时,它是一个整数,然而当它等于-1时表示有错误发生,也就是说整数类型客串了布尔类型

3)确保使用了所有已声明的变量

有人做过研究,发现未引用的变量数量与错误呈正相关,所以,请养成检查代码已确认使用了所有声明的变量的习惯,有些语言如Python等引入了行为规范来确保这一点,另外一些代码检查工具也能对未用到的变量给出警告。

#### CHECKLIST

每次写完代码后,对照这个checklist检查一遍

1)每个子程序都检查其输入参数的正确性了吗?

2)变量声明位置靠近变量第一次使用的位置吗?

3)适当得重新初始化"需要重复执行的代码"里的变量了吗?

4)所有变量都被定义未最小的作用域了吗?

5)各变量的引用点都尽可能集中在一起了吗?变量的整个声明周期都这样做了吗?

6)所有声明的变量都用到了吗?

7)变量都在合适的时间绑定吗?

8)每个变量都有且仅有一项用途吗?

9)每个变量的含义都很明确且没有隐含意义吗?

<<代码大全>>阅读笔记之一 使用变量的一般事项的更多相关文章

  1. <<代码大全>>阅读笔记之二 变量名的力量

    1.变量命名的注意事项 1)可理解性 变量要望文知义,看到这个变量不用看其他的代码就知道这个变量表示什么意思 好的变量命:currentDate, heartRate 糟糕的变量名:newButton ...

  2. 代码大全读书笔记 Part 1

    简单的看了前言,印象最深的还是这本书崇尚"绝不注水"的原则.现实生活中,不仅仅有注水牛肉,瘦肉精的猪肉,很多书籍也是东拼西凑来的内容,不注水的厚书,是十分令人期待的. 第一章:欢迎 ...

  3. 《代码大全2》读书笔记 Week8

    这一周博主阅读了<代码大全2>第11章至第13章,第三部分——"变量"就结束了,第四部分作者将转入语句的讨论. 第十一章作者详细阐述了变量名的有效命名规则,第十二和十三 ...

  4. 《代码大全2》读书笔记 week 7

    博主终于继续更<代码大全2>了 (*´・ω・`)⊃,课上老师一再强调读书笔记要写出自己的心得不能简单摘抄,所以我现在基本上只会写一下自己在阅读过程中印象深刻或者有发散思考的地方,字数可能 ...

  5. [置顶] Linux协议栈代码阅读笔记(一)

    Linux协议栈代码阅读笔记(一) (基于linux-2.6.21.7) (一)用户态通过诸如下面的C库函数访问协议栈服务 int socket(int domain, int type, int p ...

  6. [置顶] Linux协议栈代码阅读笔记(二)网络接口的配置

    Linux协议栈代码阅读笔记(二)网络接口的配置 (基于linux-2.6.11) (一)用户态通过C库函数ioctl进行网络接口的配置 例如,知名的ifconfig程序,就是通过C库函数sys_io ...

  7. 《代码大全2》读书笔记 Week9

    本周阅读了<代码大全2>第14章至第17章,这几章对我们熟悉的直线型代码.条件语句.循环语句和一些不常用的控制结构(如goto.try-catch结构)提出了一些使用建议,以下分享条件语句 ...

  8. 《代码大全2》读书笔记 Week2

    <代码大全2>第四.五章 第四章“关键的‘构建’决策”主要有以下三要点:1.每种编程语言都有优点和缺点,程序员应根据需要选择编程语言,尽量选择熟悉的语言以提高生产效率.作为一种表达工具,编 ...

  9. Linux协议栈代码阅读笔记(二)网络接口的配置

    Linux协议栈代码阅读笔记(二)网络接口的配置 (基于linux-2.6.11) (一)用户态通过C库函数ioctl进行网络接口的配置 例如,知名的ifconfig程序,就是通过C库函数sys_io ...

随机推荐

  1. 使用VS2013操作MYSQL8 (ADO.NET方式 & EF6)

    今天有时间测试了一下通过.net环境操作MYSQL数据库,测试过程及结果记录如下: 1.MYSQL安装 (1)我是从MYSQL官网下载的最新版,即MYSQL8.0,在MySql官网的下载页面,找到“M ...

  2. [AI开发]零数学公式告诉你什么是(卷积)神经网络

    大部分介绍神经网络的文章中概念性的东西太多,而且夹杂着很多数学公式,读起来让人头疼,尤其没什么基础的人完全get不到作者想要表达的思想.本篇文章尝试零公式(但有少量数学知识)说清楚什么是神经网络,并且 ...

  3. 如何使用git上传代码

    首先在github 上创建好远程仓库,并拷贝仓库地址,接下来按照以下步骤:   1.打开命令行进入要上传的文件目录,初始化 git init  2. 建立远程仓库,git remote add ori ...

  4. zabbix导入数据库报错1046 (3D000) : No database selected

    Zabbix导入数据库时报错 使用如下命令导入Zabbix数据库时报错 zcat /usr/share/doc/zabbix-server-mysql/create.sql.gz | mysql -u ...

  5. 在Linux上安装 nessus

    Nessus有三种安装方式 1.源文件安装 源文件安装是最复杂的安装方式,用此方式安装可以修改配置参数. 2.rpm安装 rpm安装比起源文件安装更简单一些,它已经把一些底层的东西写好了,用户只要按步 ...

  6. CSP2019知识点整理

    也算是接下来二十天的复习计划吧 仅止于联赛难度左右 基础算法 字符串 char[] cstring memset() 输入无& gets(), fgets(stdin, ,); strcmp, ...

  7. 暑期集训20190726 跳动(skip)

    [题目描述] 福州三中的操场上有着数不尽的跳动的小朋友. 当然善于思考的你总能从中发掘出不一样的问题 福州三中的跑道是一个n个格子围成的圆形,从0~n-1编号,有m个同学,第i个同学步长为a[i], ...

  8. 最新开源JavaScript 图表库 ECharts推荐

    ECharts是一款由百度前端技术部开发的,基于Javascript的数据可视化图表库,提供直观,生动,可交互,可个性化定制的数据可视化图表. ECharts 提供大量常用的数据可视化图表,底层基于Z ...

  9. Vue基础系列(二)——Vue中的methods属性

      写在前面的话: 文章是个人学习过程中的总结,为方便以后回头在学习. 文章中会参考官方文档和其他的一些文章,示例均为亲自编写和实践,若有写的不对的地方欢迎大家指出. 作者简介: 一个不知名的前端开发 ...

  10. jquery each循环遍历完再执行的方法

    jquery each循环遍历完再执行的方法 因为each是异步的 所以要加计数器. var eachcount=0; <pre> $(".emptytip").eac ...