软件工程与计算II

SE-II-ch18-代码设计

软件工程与计算II
目录

# 代码设计

# 1. 设计易读的代码

  1. 维护的需要(维护的工作量已经超过了开发的工作量)
    1. 50%-90%的维护时间在于阅读代码
  2. 团队协作的需要

# 1.1. 代码规范

# 1.1.1. 布局格式

  1. 用缩进与对齐表达逻辑结构(Python)
    1. 统一缩进格式一或者缩进格式二,主要符合团队编程的习惯即可
    2. IDEA统一格式化:Ctrl + Alt + L

  1. 将相关逻辑组织在一起
    1. 成员变量声明
    2. 构造方法和析构方法
    3. public方法
    4. protected方法
    5. private方法

  1. 将空行分隔逻辑(将大规模的逻辑划分的片段进行分隔)
  2. 将语句进行分隔(将过长的语句分隔到几行中进行显示)

# 1.1.2. 命名

# 1.1.3. 注释

  1. 怎么写:去Github学习

  1. JavaDoc可以生成API文档

  1. 例子:

  1. 类内部注释

  1. 例子

# 2. 设计易维护的代码

# 2.1. 小型任务

# 2.2. 复杂决策

  1. 使用新的布尔变量,代替复杂决策

  1. 使用有意义的名称封装复杂决策

  1. 表驱动

# 2.3. 数据使用

# 2.4. 明确依赖关系

  1. 类之间模糊的依赖关系会影响到代码的理解与修改,非常容易导致修改时产生未预期的连锁反应。

# 3. 设计可靠的代码 重要

# 3.1. 契约式设计

测试驱动开发也是一种契约式编程,将测试用例是否通过作为契约

# 3.1.1. 异常方式

  1. 代码会很臃肿【需要检查前置条件和后置条件

# 3.1.2. 断言方式

  1. Java提供的断言语句:assert (Expression1(: Expression2));
  2. Expression1是一个布尔表达式,在契约式设计中可以将其设置为前置条件或后置条件
  3. Expression2是一个值,如果存在,则会在抛出异常的时候作为参数构造AssertionError,即Expression2是用来在抛出异常时作为信息提示用的

# 3.2. 防御式编程

# 3.3. 表驱动编程

  1. 复杂逻辑到决策表再到表驱动

# 4. 使用模型辅助设计复杂的代码

编程也可以使用一些模型方法帮助设计复杂代码

  1. 决策表:多个if/else
  2. 伪代码:在纸或者白板上
  3. 程序流程图

# 4.1. 决策表

条件和行动 规则
条件声明 条件选项
行为声明 行为选项

  1. 决策表有效地保证了决策分析的完备性,可以和表驱动编程结合使用。

# 4.2. 伪代码

  1. 结合课本详细的描述
  2. 使用了IF、THEN、ELSE、DO、DO WHILE、DO UNTIL等关键字来表示程序的逻辑组织。
  3. 通过类似编程语言的缩进方式来表明程序逻辑
  4. 使用尽可能短的语句,只是用名词和动词,避免使用容易产生歧义的形容词的使用
  5. 实例详见课本P312页

# 4.3. 程序流程图

  1. 圆角:开始或者结束
  2. 平行四边形:输入或输出
  3. 直角:处理步骤
  4. 菱形:控制结构

# 5. 为代码开发单元测试用例

# 5.1. 为方法开发测试用例

# 5.1.1. Sales方法

  1. 使用桩程序代替没有写的方法

# 5.2. 使用Mock Object测试类的方法

# 5.3. 为类开发测试用例

  • 我们使用状态图来辅助我们分析,通过状态图生成测试用例线索表,最后生成一个测试用例

# 6. 代码复杂度度量 重要

  • 重要:这里涉及到两种计算方法 圈复杂度

# 6.1. 度量的意义

$类的加权方法 = \sum_{i-1}^{n}C_{i}$

# 7. 代码大全(书) 【不做要求】

# 7.1. 变量

# 7.1.1. 变量定义

# 7.1.2. 变量初始化

  1. 使用内存访问工具来检查所有的指针的有效性。

# 7.1.3. 作用域

  1. 生命周期越长越容易出现问题

# 7.1.4. 减少作用域的一般原则

# 7.1.5. 持续性

# 7.1.6. 为变量制定单一用途

  1. 哪怕是临时变量也尽量避免重复使用。

# 7.1.7. 两个变量用于两种用途

# 7.1.8. 避免让代码具有隐含意义

# 7.1.9. 变量的命名

  1. 一定要用规范的方式命名变量

# 7.2. 数值理论

  1. 整数:
    1. 检查整数除法
    2. 检查整数溢出
    3. 检查中间结果溢出(浮点运算)

# 7.3. 创建子程序的正当理由

# 7.4. 子程序的命名

# 7.5. 算法的设计

  1. 了解编译器的优化

# 7.6. 一般控制问题

# 7.7. 空语句

# 7.8. 更加清晰的非空循环体

# 7.9. 处理危险的深层嵌套

# 8. 问题代码与建议

# 8.1. [Green 1997] How to Write Unmaintable Code