《代码大全2》阅读笔记12 Chapter 19 General Control Issues

Chapter 19 General Control Issues
 一般控制问题

19.1 Boolean Expressions 布尔表达式
1. Using true and false for Boolean Tests 用true和false做布尔判断
 在布尔表达式中应该用标识符true和false,而不要用0和1等数值。
2. 隐式地比较布尔值与true和false
 例如:while(not done) ... 和 while(a>b),而不要写成while(done = false)... 和

while((a>b)=true)...

·Marking Complicated Expressings Simple 简化复杂的表达式
1. 拆分复杂的判断并引入新的布尔变量
2. 把复杂的表达式做成布尔函数
3. 用决策表代替复杂的条件 (表驱动法)
 有时候一个很复杂的判断,其中涉及到多个变量。这时用一个决策表(decision-table)代

替if或者case语句来执行判断可能非常有帮助。决策表查询起来很容易。降低了复杂度,也降低了出错

的可能性。 如果你的数据变了,只需要修改决策表即可,而无须改动代码。

·Forming Boolean Expressions Positively 编写肯定形式的布尔表达式
1. 在if语句中,把判断条件从否定形式转换为肯定形式,并且互换if和else子句中的代码。
2. 用狄摩根定理简化否定的布尔判断
 例如: if(!displayOK || !printerOK) ... 等同于 if( !(displayOK && printerOK))...
 狄摩根定理的逻辑表达式的转换法则:
 not A and not B   not(A or B)
 not A and B   not(A or not B)
 A and not B   not(not A or B)
 A and B    not(not A or not B)
 not A or not B   not(A and B)
 not A or B   not(A and not B)
 A or not B   not(not A and B)
 A or B    not(not A and not B)

·Using Parentheses to Clarify Boolean Expressions
 用括号使布尔表达式更清晰
1. 用一种简单的技术技巧使括号对称
if ( ( ( a < b ) == ( c == d ) ) && !done ) ...
0 1 2 3        2      3           2 1              0
开始的时候说“0”, 然后从左到右扫描该表达式。最后的时候所得结果为0,那么你的括号就是配对的。

·Knowing How Boolean Expressions Are Evaluated
 理解布尔表达式是如何求值的
一些语言的编译器会先计算布尔表达式中的每个项的值,然后再把这些项组合起来求出整个表达式的值


一些语言的编译器采用“短路short-circuit”或者“惰性lazy”求值,只求出那些必须的部分。
当你希望用第一个判断的结果来控制第二个判断是否执行时,这一点就显得尤为重要了。

·Writing Numberic Expressions in Number-Line Order
 按照数轴的顺序编写数值表达式
应该很好地组织数值判断,使其顺序与数轴上的点排列顺序相符。一般来说,应该把数值判断组织好,

使你能有像下面这样的比较方式:
MIN_ELEMENTS <= i and i <= MAX_ELEMENTS
i < MIN_ELEMENTS OR MAX_ELEMENTS < i
这里的关键点在于要从左到右,从小到大地排列元素。
 第一行中,MIN_ELEMENTS和MAX_ELEMENTS是两个端点,所以把它们放在两边。变量i

应该位于两点之间,所以在中间。
 第二行中,想判断i是否位于范围之外,因此把i写在判断外围两端的位置,而把

MIN_ELEMENTS和MAX_ELEMENTS写在里面。

·Guidelines for Comparisons to 0 与0比较的指导原则
1. 隐式的比较逻辑变量
2. 把数和0相比较
3. 在C中显示地比较字符和零终止符(‘\0’)
4. 把指针与NULL相比较

·Common Problems with Boolean Expressions 布尔表达式的常见问题
1. 在C家族语言中,应该把常量放在比较的左端
2. 在C++中,可以考虑创建预处理宏来替换&&, || 和==。(不得已才这么做)
3. 在JAVA中,应理解a==b和a.equals(b)之间的差异。
 前者判断a和b是否引用了同一个对象。
 后者判断的是这两个对象是否具有相同的值。

19.2 Compound Statements(Blocks)
 复合语句(语句块)
1. 把括号对一起写出
2. 用括号来把条件表达清楚

19.3 Null Statements 空语句
C++中可以写空语句,即一条仅含有分号的语句。一些原则:
1. 小心使用空语句
2. 为空语句创建一个DoNothing()预处理宏或者内联函数
 毫无争议的表明“这里不希望做任何事情”的用意。
 例如:#define DoNothing()
 while(...){
  DoNothing();
 }
3. 考虑如果换用一个非空的循环体,是否会让代码更清晰
 空循环体代码的产生多数都是为了利用循环控制代码的副作用(side effects)。

19.4 Taming Dangerously Deep Nesting 驯服危险的深层嵌套
1. 通过重复检查条件中的某一个部分来简化嵌套的if语句
 你不能无偿地减少嵌套层次;作为减少嵌套层次的代价,你必须要容忍使用一个更复杂的判

断。
2. 用break块来简化嵌套if。
 例如:if(condition1) break;
 if(condition2) break;
 ...
 这种技巧很不常见,所以只有在你的团队都很熟悉这种技巧,并且已经把它纳入了团队可接

受的编码实践以后,才可以使用。
3. 把嵌套if转换成一组if-then-else语句
4. 把嵌套if转换成case语句。
5. 把深层嵌套语句抽出来放进单独的子程序
6. 使用一种更面向对象的方法。
7. 重新设计深层嵌套的代码

19.5 A Programming Foundation: Structured Programming 编程基础:结构化编程
 结构化编程的核心思想很简单,那就是一个应用程序应该只采用一些单入单出的控制结构。

单入单出的控制结构指的就是一个代码块,他只能从一个位置开始执行,并且只能结束于一个位置。除

此之外再无其他入口或出口。结构化编程和结构化的,自上而下的设计不完全一样。前者只适用于编码

层。
 一个结构化的程序将按照一种有序的且有规则的方式执行,不会做不可预知的随便跳转。你

可以自上而下的方式阅读它,而它执行起来也大体是遵循这个顺序的。使用规则性不强的方法所生成的

源代码,很难有意义且形象地反映出程序是如何在机器上执行的。可读性差意味着不容易理解,最终导

致应用程序的低质量。
 时至今日,结构化编程的核心概念仍然很有用,在使用break,continue,throw,catch,

return,考虑其他问题时都需要这些概念。

·The Three Components of Structrued Programming 结构化编程的三个组成部分
1. Sequence 顺序
2. Selection 选择
 选择是一种有选择的执行语句的控制结构。if-then-else语句就是一个常见的例子。

3. Iteration 迭代
 迭代是一种使一组语句多次执行的控制结构。成被称为“循环”。

结构化编程的中心论点是,任何一种控制流都可以由顺序,选择和迭代这三种结构生成。

19.6 Control Structures and Complexity 控制结构与复杂度
 控制结构之所以受到了如此多的关注,就是因为它们对程序整体复杂度的影响非常大。控制

结构用得不好就会增加复杂度;反之能降低复杂度。

·How Important is Complexity 复杂度的重要性
软件的首要任务:管理复杂度

·Greneral Guidelines for Reducing Complexity 降低复杂度的一般原则
1. How to measure Complexity 如何度量复杂度
 衡量复杂度的方法中,最著名的可能就是Tom McCabe的方法了。该方法通过计算子程序中“

决策点(decision points)”的数量来衡量复杂度。下面给出一些用于计算决策点的方法:
 a. 从1开始,一直往下通过程序。
 b. 一旦遇到一下关键字,或者同类的词,就加1:if, while, repeat, for, and, or.
 c. 给case语句中的每一种情况都加1.
 举例:
 if((status=Success) and done) or (not done and (numLines >= maxLines))

then ...
 这段代码中,从1算起,遇到if得2,and得3, or得4,and得5。加起来,这段代码包含5个

决策点。 

·What to Do with Your Complexity Measurement 如何处理复杂度的度量结果
 计算出来的决策点的数量以后,你就可以得到数值分析你写的子程序的复杂度了:
 0-5  子程序可能还不错
 6-10 得想办法简化子程序了
 10+ 把子程序的某一个部分拆分成另一个子程序并调用它
10个决策点的上限并不是绝对的。应该把决策点的数量当做一个警示,该警示说明某个子程序可能需要

重新设计了。不要死守这个规则。

Key Points 要点
1. 使布尔表达式简单可读,将非常有助于提高你的代码的质量。
2. 深层次的嵌套使得子程序变得很难以理解。所幸的是,你可以相对容易地避免这么做。
3. 结构化编程是一种简单并且仍然使用的思想:你可以通过把顺序,选择和循环三者组合起来而开发出

任何程序。
4. 将复杂度降低到最低水平是编写高质量代码的关键。

Desire has no rest.
原文地址:https://www.cnblogs.com/samcn/p/1453241.html