看了好久代码大全,最后全忘记了...留下的只是潜移默化的一些迷糊的东西,或许本书本身目的就在于此吧。不是要求程序员刻意按照每个要求,只是为写代码提供了一些基本准则。很不错的一本书,提高写代码的修养。还是给了我很多启发。
- 今后更加规范的写代码
- 注意每个细节
- 要做谦虚的程序员
- 想起了张无忌学太极拳
隐喻
隐喻通过把软件开发与你所熟知的事情联系在一起,从而使你对其有更深刻的理解。
· 一些隐喻要好于其它隐喻。
· 把软件创建与建造建筑物类比,表明开发软件前要精心准备,并表明了大规模项目与小
规模项目之间的差别。
· 认为软件开发实践是智能工具箱中的工具进一步表明,每个程序员都有许多自己的工
具,没有任何一种工具是万能的。为每件工作选择合适的工具,是成为一个优秀程序员 的首要素质之一。
创建子程序
· 是否检查过先决条件已经满足了?
· 定义子程序将要解决的问题了吗?
· 结构设计是否足够清楚,使得你可以给子程序起个好名字?
· 考虑过如何测试子程序了吗?
· 是否从模块化水平或者满足时间和内存需求角度考虑过效率问题?
· 是否查阅过参考书;以寻找有帮助的算法?
· 是否用详尽的 PDL 设计子程序?
· 在必要时,是否在逻辑设计步骤前考虑了数据?
· 是否检查过PDL,它很容易理解吗?
· 是否注意到了足以使你返回到结构设计阶段的警告(使用了全局数据,更适合其它子
程序的操作,等等)。
· 是否使用了PDL到代码流程,是否把PDL作为编码基础并把原有的PDL转为注释?
· 是否精确地把PDL翻译成了代码?
· 在作出假设时,验证它们了吗?
· 是从几个设计方案中选择了最好的,还是随意选择了一个方案?
高质量的子程序
-
总体问题
· 创建子程序的理由充分吗?
· 如果把一个子程序中的某些部分独立成另一个子程序会更好的话,你这样做了吗?
· 是否用了明显而清楚的动宾词组对过程进行命名?是否是用返回值的描述来命名函
数?
· 子程序的名称是否描述了它做的所有工作?
· 子程序的内聚性是不是很强的功能内聚性?它只做一件工作并做得很好吗?
· 子程序的耦合是不是松散的?两个子程序之间的联系是不是小规模、密切、可见和灵
活的?
· 子程序的长度是不是它的功能和逻辑自然地决定的:而不是由人为标准决定的? -
防错性编程
· 断言是否用于验证假设?
· 子程序对于非法输入数据进行防护了吗?
· 子程序是否能很好地进行程序终止?
· 子程序是否能很好地处理修改情况?
· 是否不用很麻烦地启用或去掉调试帮助?
· 是否信息隐蔽、松散耦合,以及使用“防火墙”数据检查,以使得它不影响子程序之
外的代码?
第五章 高质量子程序的特点 74
· 子程序是否检查返回值?
· 产品代码中的防错性代码是否帮助用户,而不是程序员? -
参数传递问题
· 形式参数与实际参数匹配吗?
· 子程序中参数的排列合理吗?与相似子程序中的参数排列顺序匹配吗? · 接口假设说明了吗?
· 子程序中参数个数是不是7个或者更少,
· 是否只传递了结构化变量中另一个子程序用得到的部分?
· 是否用到了每一个输入参数?
· 是否用到了每一个输出参数?
· 如果子程序是一函数,是否在所有情况下它都会返回一个值?
模块的质量
· 模块是否有一个中心目的?
· 模块是否是围绕着一组公用数据进行组织的?
· 模块是否提供了一套相互联系的功能?
· 模块功能是否足够完备,从而使得其它模块不必干预其内部数据?
· 一个模块相对其它模块是否是独立的?它们之间是松散耦合的吗?
· 一个模块的实现细节,对其它模块来说,是隐含的吗?
· 模块的接口是否抽象到了不必关心其功能实现方式的地步?它是作为一个黑盒子来设
计的吗?
· 是否考虑过把模块再划分为单元模块?是否对其进行了充分的再划分工作?
· 如果用不完全支持模块的语言编程,你是否制定了编程约定以使这种语言支持模块?
高层次设计
本表给出了在评估设计质量时,通常要考虑一些问题。本表是 3.4 节中结构设计检查表的
补充,这个表所考虑的主要是设计质量。3.4 节中的检查表则侧重于结构设计和设计内容。这 个表中的某些内容是相互重合的。
· 是否使用了往返设计方法,应从几个方案中选择最好的,而不是首次尝试就确定方案。
· 每个子程序的设计是否都和与其相关的子程序设计一致?
· 设计中是否对在结构设计层次上发现但并未解决的问题作了充分说明?
· 是否对把程序分解成对象或模块的方法感到满意?
· 是否对把模块分解成子程序的方法感到满意?
· 是否明确定义了子程序的边界?
· 是否是按照相互作用最小的原则定义子程序的?
· 设计是否充分利用了自顶向下和自底向上法?
· 设计是否对问题域要素、用户接口要素、任务管理要素和数据管理要素进行了区分?
· 设计是智力上可管理的吗?
· 设计是低复杂性吗?
· 程序是很容易维护的吗?
· 设计是否将子程序之间的联系保持在最低限度?
· 设计是否为将来程序可能扩展作了准备?
· 子程序是否是设计成可以在其它系统中再使用的?
· 低层次子程序是高扇入的吗?
· 是否绝大多数子程序都是低或中等程度扇出的?
· 设计易于移植到其它环境吗?
· 设计是简练的吗?是不是所有部分都是必要的?
· 设计是成层的吗?
· 设计中是否尽量采用了标准化技术以避免奇特的、难以理解的要素?
数据名称
- 通用命名约定
· 变量名称是否完全准确地描述了变量代表的是什么?
· 变量名是否指向是客观世界中的问题,而不是关于这问题的用程序语言表达解决方案? · 变量名称是否是够长,使得你不必破译它?
· 变量名中如果含有计算限定词的话,是否将其放在最后?
· 是否在名称中用Count或Index来代替了Num? - 对特殊类型数据的命名
· 循环变量的名称是有意义的吗?(如果循环体较长是嵌套循环的话,应用有含义的名
· · ·
称来代替 i、j、k 之类的名称) 是否用更富于含义的名称来代替了被叫作"tempotarg"的临时变量? 当逻辑变量的值是"True"时,它的名称是否充分表达了其含义?
是否用前缀或后缀来表明了某些枚举类型是一类的?如用 Color 来作 ColorRed, ColorGreen,ColorBlue 等枚举类型的前缀。
· 命名常量的名称是否是指向它们代表的实体而不是它们所代表的数值的? - 命名约定
· 命名约定是否区分了局部、模块和全局数据?
· 命名约定是否对类型名称、命名常量、枚举类型和变量进行了区分?
· 在不支持强化仅供子程序输入参数的语言中,命名约定是否对这类参数进行了标识?
· 命名约定是不是与程序语言的标准约定尽可能地相容?
· 对于语言中没有强制的子程序中仅做输入的参数,是否约定将它标识了?
· 是否对名称进行了格式化以增强程序的可读性?
短名称
· 代码是否使用了长名称?(除非有必要使用短名称)
· 是否避免了只省略一个字母的缩写?
· 所有单词保持缩写的连续性了吗?
· 所有的名称都是容易发音的吗?
· 是否避免了会引起错误发音的名称?
· 是否在注释表中对短变量名进行了注释? - 避免如下这些常见的命名错误了吗
· 易引起误会的名称
· 含义相似的名称
· 仅有一或两个字母不同的名称
· 发音相似的名称
· 使用数字的名称
· 对单词作改写以使其比较短的名称
· 英语中常拼写错的名称
· 标准库子程序或已定义的变量名又定义了
· 完全是随意的名称
· 含有难以辨识字母的名称
变量
- 一般数据
· 是否已经使变量的作用域尽可能地小?
· 是否把对变量的使用集中到了一起?
· 控制结构与数据结构是相对应的吗?
· 每个变量是否有且仅有一个功能?
· 每个变量的含义都是明确的吗?是否保证了每个变量都没有隐含的意义?
· 每一个说明过的变量都被用到了吗? - 全局变量
· 是否是在迫不得已的情况下,才使某些变量成为全局的?
· 命名约定是否对局部、模块和全局变量进行了区分?
· 是否说明了所有全局变量?
· 程序中是否不含有伪全局变量——传往各个子程序的庞大而臃肿的数据结构?
· 是否用存取子程序来代替了全局数据?
· 是把存取子程序和数据组织成模块而不是随意归成一堆的吗?
· 存取子程序的抽象层次是否超过了程序语言实现细节?
· 所有相互有联系的存取子程序,其抽象程度都是一致的吗?
基本数据
- 常数
• 代码中是否避免了”奇异数”(常数?)
• 程序中是否采取了措施来防止出现被“0”除错误?
• 类型转换是显式进行的吗?
• 如果在同一个表达式中出现了两种不同类型的变量,是否对表达式按照你的意愿进行
求值?
• 程序中是否避免了混合类型比较?
• 在编译过程中是没有警告的吗? - 整型数
• 使用整型数相除表达式的结果是否与预期的一致? • 整型数表达式中是否避免了整型数溢出问题? 浮点数
• 是否避免了数量级相差过大的数之间加减运算?
• 程序中是否系统地采取措施来防止舍入误差问题? • 程序中是否避免了对浮点数进行相等比较? 字符和字符串
• 程序中是否避免了常数型字符和字符串?
• 对字符串的引用是否避免了边界错误?
• 程序中是否使用了附加的逻辑变量来说明条件判断?
• 程序中是否使用了附加的逻辑变量来简化条件判断? - 枚举类型
• 程序中是否用枚举类型代替了命名常量来改善可读性、可靠性和易改动性?
• 是否用了枚举类型代替逻辑变量以改进可读性和灵活性?
• 在使用了枚举类型的判断中是否检查了无效值?
• 枚举类型的第一个入口是否是保留为无效的? - 命名常量
• 在数据说明中使用的是命名常量吗?
• 是否一致地使用了命名常量,而不是一会儿使用命名常量,一会儿使用数值? - 数组
• 是否所有的下标都在数组界限之内?
• 是否对数组所有的引用都没有发生越界错误?
• 多维数组的下标排列顺序正确吗?
• 在嵌套循环中,作为循环变量的数组下标是正确的吗?是否出现了交叉错误?
顺序控制
- 组织顺序式程序代码
· 把语句间的依赖关系表示得很清楚吗?
· 子程序名是否把依赖关系表示得很清楚?
· 子程序的参数是否把依赖关系表示得很清楚?
· 若代码的依赖关系不清楚,用注释注明了吗?
· 代码能从上读到下吗?
· 变量的出现靠得很近吗? ——从跨度和存活时间来考虑。
条件控制
- 条件语句 if-then 语句
• 正常情况路径在代码中流向是否很分明?
• if-then 语句在出现等号时流向是否正确?
• else 语句是否有必要?
• else 语句正确吗?
• if 语句和 else 语句正确吗?它们是否弄反了?
• 正常情况是否跟在 if 后而非 else 后? if-then-else 语句
• 复杂的条件是否封装成布尔函数调用了?
• 最常见情况放在前面吗?
• 全部情况都覆盖住了吗?
• if-then-else 语句是最好的选择吗?——用 case 语句代替是否更好? case 语句
• 各情况的安排次序有含义吗?
• 每种情况对应的操作简单吗?——如需要调用别的子程序。
• case 语句中的变量有实际意义吗?它是为了用 case 语句而单纯地定义出来的伪变量
吗?
• 缺省语句的用法是否合法(规范)?
• 用缺省语句检查和报告异常情况吗?
• 在 C 语言中,每一情况的结尾用了 break 了吗?
循环
· 循环是从顶部进入的吗?
· 循环的初始化是靠近着循环顶部的吗?
· 循环是死循环还是事件驱动循环?它的结构比诸如 for i := 1 to 9999 之类的更清楚吗?
· 是C的for循环吗?循环头包含了全部的循环控制条件了吗?
· 循环体用begin和end或类似的结构去标明以免在修改时出错了吗? · 空循环还是非空循环?
· 把循环内务处理归结到一起了吗?放在头部还是放在结尾了?
· 循环是完成一个且仅完成一个功能吗?(像一个子程序一样)
· 循环在所有可能情况下都能退出吗?
· 循环的中止条件明显吗?
· 如果是for循环,在循环体内有没有改变控制变量而使循环强行退出?
· 循环体内部用一个变量保留重要循环控制变量的值,而不在循环体外引用控制变量的
终值吗?
· 循环用了安全计数器了吗?
· 循环控制变量是整数类型吗?
· 循环控制变量是否有一个有含义的名字?
· 避免了控制变量的冲突没有?
· 循环短到可一目了然地步了吗?
布局
- 简述
· 格式化的本意是要显示代码的逻辑结构吗?
· 格式化的形式能始终一致吗?
· 格式化后使代码易于维护吗?
· 格式化后改进了可读性吗? - 控制结构
· begin-end 对中代码避免再次缩排了吗? · 一系列的块结构用空行相互分隔了吗? · 复杂的表达式格式化后可读性增强了吗? · 单条语句块始终一致地格式化了吗?
· Case 语句的格式化与其它控制结构格式化相协调吗?
· goto 语句格式化后自己显得更清楚了吗? - 单条语句
· 把单条语句分成几行,每行都明显地不能作独立行看待了吗? · 续行有意识地退格了吗?
· 相关语句组对齐了吗?
· 不相关语句组不应对齐,你是这样的吗?
· 每行至多含一条语句吗?
· 每个语句避免副作用了吗?
· 数据定义时相应项对齐了吗?
· 每行至多定义一个数据,是吗? - 注释
· 注释行与它所对应的代码退同样格数了吗?
· 注释行的形式易修改吗? - 子程序
· 子程序的参量格式化后各参数易读、易修改、易加注释吗?
· 在C中是否用新子程序定义方法呢?
· Fortran 中,参数定义是否和局部变量定义分开? - 文件、模块和程序
· 若语言允许有多个源文件,每个源文件仅含一个模块是吗?
· 一个文件内的各子程序是否用空行清楚隔开?
· 如果一个文件含几个模块,那么每个模块中的子程序是否被组织到被清楚隔开? · 各子程序是否按字母顺序排列?
网友评论