软件实现与测试

软件实现

软件工程 第四部分 第9章,主讲人:李欣

Created: 2023-05-16 Tue 02:07

0.1. 互动课堂

Click to host the seminar.

0.2. 签到

https://xin.blue/tool/attendance/

0.3. 本次课的目标

  • 第四部分:软件实现与测试
    • 第9章:软件实现
      • 程序设计语言
      • 程序设计风格
      • 编码规范
      • 程序效率与性能分析

1. 程序设计语言

程序编码阶段的 任务 是:

将软件的 详细设计 转换成用程序设计语言实现的 程序代码

因此,程序设计语言的 性能设计风格 对于程序设计的 效能质量 有着直接的关系。 语言的 工程特性软件开发项目的成功与否 也有着重要的影响。

1.1. 程序设计语言的性能

从以下 角度 对程序设计语言的 性能 进行讨论:

%%{init: { 'theme': 'forest', 'fontFamily': 'Times New Roman, KaiTi' }}%%
flowchart TB
    A["讨论性能的角度"]
    A --> B["软件心理学"]
    A --> C["软件工程"]
    B --> BA["使用方便"]
    B --> BB["简明易学"]
    B --> BC["......"]
    C --> CA["可移植性"]
    C --> CB["可维护性"]
    C --> CC["......"]   

performance.svg

Figure 1: 程序设计语言的性能

1.1.1. 软件心理学的观点

软件心理学 研究的任务是:

  • 关注人们对软件所关心的某些方面,如
    • 使用方便
    • 简明易学
    • 可靠性
    • 减少故障发生率
    • 使用户更加满意
    • ……
心理学的观点下影响程序员心理的语言特性包含的几方面
  • 一致性 :它表示一种语言所使用符号的 兼容程度 ,以及 允许随意规定限制、允许对语法或语义破例的程度
  • 二义性 :虽然语言的 编译程序 总是以一种机械的规则来解释语句,但 读者 则可能用不同的方式来理解语句。
  • 简洁性 :表示为了用该语言编写程序 必须记忆 的关于代码的 信息量 。在语言的属性中, 简洁性的标志 是:
    • 语言支持 BLOCK 构造和 结构化程序能力强
    • 可使用的 保留字缩写字种类少
    • 数据类型种类少 ,提供 缺省说明
    • 算术运算符逻辑运算符种类少
  • 局部性 :程序设计语言的 综合特性
  • 传统性 :人们学习一种新的程序设计语言的能力受到 传统的影响

1.1.2. 软件工程的观点

软件工程的观点 下程序设计语言的特性应着重考虑 软件开发项目的需要

工程上对程序编码的性能要求
  • 详细设计 应能 直接容易地 翻译成 代码程序
  • 源程序 应具有 可移植性
    • 对源程序 不做修改少做修改 就可以实现 处理器上的移植编译程序上的移植
    • 即使程序的 运行环境改变 (例如,改用一个新版本的操作系统),也 不用修改源程序
    • 源程序的许多模块可以 不做修改少做修改 就能 集成为功能性的各种软件包 ,以 适应不同的需要
  • 编译程序 应具有 较高的效率
  • 尽可能应用 代码生成的自动工具
  • 可维护性
    • 源程序的 可读性
    • 语言自身的 文档化特性

1.2. 程序设计语言的分类

  • 第一代语言 :从属于机器的语言
  • 第二代语言 :汇编语言
  • 第三代语言 :高级程序设计语言
  • 第四代语言(Fourth Generation Language, 4GL)

1.2.1. 4GL的优缺点

4GL的优点
  • 由于面向问题、非过程化程度高,可以成数量级地提高软件生产率,缩短软件开发周期;
  • 以数据库管理系统所提供的功能为核心,进一步构造了开发高层软件系统的开发环境;
  • 提供了功能强大的非过程化问题定义手段。
4GL的缺点
  • 4GL在 整体能力 上与3GL具有 一定的差距
    • 语言抽象级别提高 导致的
    • 许多4GL 只面向专项应用
  • 由于4GL的 抽象级别较高 ,因此系统运行的 开销大效率低
  • 由于 缺乏统一的工业标准 ,因此4GL产品 种类繁多用户界面差异很大
  • 目前4GL主要面向 基于数据库应用的领域 ,不宜于 科学计算实时系统系统软件开发

1.2.2. 4GL的分类

按照功能将4GL划分的几个类别
  • 查询语言和报表生成器
    • 查询语言数据库管理系统 的主要工具,它提供 用户对数据库进行查询 的功能。
    • 报表生成器 是为用户提供的 自动产生报表 的重要工具,它提供 非过程化的描述手段 , 让用户很方便地 根据数据库中的数据生成报表
  • 图形语言数据流图模块结构图程序流程图
  • 应用生成器
    • 交互式应用生成器 :允许用户以可见的交互方式在终端上创建文件、报表等。
    • 编程式应用生成器 :为建造复杂系统的专业程序人员而设计。
  • 形式化规格说明语言 :解决了自然语言的 歧义性不精确性 等问题,是 软件自动化的基础

1.3. 程序设计语言的选择

为某个特定开发项目选择编程语言时, 既要从 技术角度工程角度心理学角度 评价和比较各种语言的 适用程度 , 又必须考虑 现实可能性

选择编程语言时需考虑的几个方面
  • 应用领域
    • 科学与工程计算机领域FORTRANCC++
    • 商业数据处理领域COBOLJavaSQL
    • 系统程序设计和实时应用领域汇编语言 或一些新的派生语言,如 AdaC++
    • 人工智能领域以及问题求解、组合应用领域LispPrologPHPPython
  • 系统用户的要求
  • 编程语言自身的功能
  • 编码和维护成本及开发环境
  • 编程人员的技能
  • 软件可移植性

2. 程序设计风格

阅读程序软件开发和维护 过程中的一个重要组成部分, 而且 读程序的时间比写程序的时间还要多 。 因此, 程序实际上也是一种供人阅读的文章

2.1. 源程序文档化

源程序文档化 包括 标识符的命名安排注释 以及 程序的视觉组织 等。

2.1.1. 标识符的命名

标识符包括
  • 模块名变量名常量名标号名子程序名数据区名缓冲区 等。
命名时应考虑
  • 名字应能 反映它所代表的实际东西 ,使其能够 见名知意 ,有助于对程序功能的理解
  • 应当选择 精炼的意义明确的 名字,才能简化程序语句,改善对程序功能的理解
  • 可使用 缩写名字 ,但需注意 缩写规则要一致 ,并且要给每个名字加 注释
  • 在一个程序中, 一个变量 只应用于 一种用途

2.1.2. 程序的注释

序言性注释
  • 通常置于每个程序模块的 开头部分 ,它应当给出程序的 整体说明
  • 对于理解程序本身具有 引导作用
  • 有关项目包括
    • 程序(模块)标题
    • 有关本模块 功能和目的的说明
    • 主要算法
    • 接口说明 ,包括调用形式、参数描述、子程序清单
    • 有关程序描述 ,包括重要的变量及其用途、约束或限制条件,以及其他有关信息
    • 模块位置 ,说明在哪一个源文件中,或隶属于哪一个软件包
    • 开发简历 ,包括模块设计者、复审者、复审日期、修改日期及有关说明等
功能性注释
  • 嵌在 源程序体中 ,用以描述 其后的语句或程序段 , 也就是解释下面要 做什么 ,或是执行了下面的语句会怎么样;
  • 用于描述 一段程序 ,而不是每一个语句;
  • 缩进和空行 ,使程序与注释容易区别;
  • 要注意 注释要正确

如下面的注释行仅仅重复了后面的语句, 对于理解它的工作没有太大作用。

/* Add amount to total */
total = amount + total;

如果注明把 月销售额 计入 年度总额 ,可方便读者理解语句意图。

/* Add monthly sales to annual total */
total = amount + total;

2.1.3. 视觉组织:空格、空行和移行

  • 空格 :恰当地利用空格,可突出 运算的优先性避免发生运算错误
  • 空行自然的程序段之间可用空行隔开
  • 移行 :也叫做 向右缩格 ,对于 选择语句循环语句 ,把其中的程序段语句 向右做阶梯式移行
// test.c
#include <stdio.h>

void main() {
  float n, s = 0, t = 1;

  for (n = 1; n <= 20; n++) {
    t *= n;
    s += t;
  }

  printf("1! + 2! + 3! + ... + 20! = %e\n", s);
}
gcc -o test test.c
gcc -o test test.c
./test
gcc -o test test.c
./test
# 1! + 2! + 3! + ... + 20! = 2.561327e+18

2.2. 数据说明标准化

为了使程序中 数据说明 更易于 理解维护 ,在编写程序时, 需要注意 数据说明的风格

具体需要注意的几点
  • 数据说明的次序 应当 规范化 ,使数据属性容易查找,也有利于测试、排错和维护。
    • 常量说明简单变量类型说明数组说明公用数据块说明
      所有的文件说明
    • 整型量说明实型量说明字符量说明逻辑量说明
  • 当多个变量名用一个语句说明时,应对这些变量按 字母顺序 排列。
    • int size, length, width, cost, price;
    • int cost, length, price, size, width;
  • 对于 复杂的数据结构 ,应当使用 注释 对其进行说明。

2.3. 语句结构简单化

  • 一行内只写一条语句 ,并且采取适当的移行格式,使程序的逻辑和功能变得更加明确。
  • 程序编写首先应当考虑 清晰性 ,不要刻意追求技巧性,使程序编写得过于紧凑。
  • 程序编写要 简单清楚 ,直截了当地说明程序员的用意。
  • 除非对效率有特殊的要求,否则程序编写的原则使 清晰第一,效率第二
  • 避免使用临时变量而使可读性下降
  • 让编译程序做简单的优化
  • 尽可能使用库函数
  • 避免不必要的转移 ,如果能保持程序的可读性,则不必用GOTO语句。
  • 尽量只采用 3种基本的控制结构 来编写程序。
  • 避免使用空的 else 语句和 if-then-if 语句
  • 避免采用过于复杂的条件测试
  • 尽量减少使用否定条件的条件语句

2.4. 输入/输出规范化

  • 对所有的输入数据都进行 检验 ,从而识别错误的输入,以 保证每个数据的有效性
  • 检查输入项的各种重要组合的 合理性 ,必要时报告 输入状态信息
  • 使得输入的步骤和操作尽可能简单,并 保持简单的输入格式
  • 输入数据时,应允许使用 自由格式输入
  • 应允许 缺省值
  • 输入一批数据时,最好使用 输入结束标志 ,而不要由用户指定输入数据数目。
  • 在以交互式输入/输出方式进行输入时,要在屏幕上使用提示符 明确提示交互输入的请求 , 指明 可使用选择项的种类取值范围
  • 当程序设计语言对输入/输出格式有严格要求时,应保持 输入格式输入语句 的要求 一致
  • 给所有的输出加 注解 ,并设计 输出报表格式

3. 编码规范

规范 涉及 版面注释标识符命名变量使用代码可测性程序效率质量保证代码编译单元测试程序版本与维护

4. 程序效率与性能分析

程序的效率 是指 程序的执行速度程序所需占用内存的存储空间

程序效率的几条准则
  • 效率是一个性能要求 ,应当在 需求分析阶段 给出。软件效率 以需求为准 ,不应以人力所及为准。
  • 好的设计可以提高效率
  • 程序的效率与程序的简单性相关

任何对效率无重要改善, 且对程序的 简单性可读性正确性 不利的程序设计方法都是不可取的。

5. 课后作业

  1. 习题9.2 一般情况下,程序的效率和清晰性相比哪一个更重要?
  2. 习题9.3 程序中的注释是否越多越好?
  3. 习题9.4 如何提高表达式的可读性?
  4. 程序的效率受哪些因素的影响?如何降低这些因素对程序效率的影响?