700 likes | 872 Views
软件实现. 内容和目的. 编程的分类 编程语言的选择 编程风格 程序效率 编码要求. 编程. 编程是设计的自然结果 编程语言的特性和编程风格会深刻地影响软件的质量和可维护性 软件实现的过程: 设计 — 源程序 — 目标代码 — 可执行代码. 编程语言的发展. 程序设计语言的发展已经历了四个阶段: 第一代语言( 1GL ),机器语言 , 面向机器的指令代码; 第二代语言( 2GL ),汇编语言,符号表示方式; 第三代语言( 3GL ),高级程序设计语言,包括结构化和面向对象的语言; 第四代语言( 4GL ),说明型程序设计语言;.
E N D
内容和目的 • 编程的分类 • 编程语言的选择 • 编程风格 • 程序效率 • 编码要求
编程 • 编程是设计的自然结果 • 编程语言的特性和编程风格会深刻地影响软件的质量和可维护性 • 软件实现的过程: 设计—源程序—目标代码—可执行代码
编程语言的发展 • 程序设计语言的发展已经历了四个阶段: • 第一代语言(1GL),机器语言,面向机器的指令代码; • 第二代语言(2GL),汇编语言,符号表示方式; • 第三代语言(3GL),高级程序设计语言,包括结构化和面向对象的语言; • 第四代语言(4GL),说明型程序设计语言;
application program development library calls Development environment Software API (system calls) OS kernel (VRTX, QNX,…) Basic I/O statements and exchanges RAM/ROM Real time clock Disk drives Ethernet drives Display drives Hardware ... CPU 基于软件开发平台的编程
OS-independent application program Statements and language library calls language libraries (C, C++,...) Software API (system calls) OS kernel (VRTX, QNX,…) Basic I/O statements and exchanges RAM/ROM Real time clock Disk drives Ethernet drives Display drives Hardware ... CPU 独立于操作系统编程
OS-dependent application program Statements and language library calls API (system calls) language libraries (C, C++,…) Software API (system calls) OS kernel (VRTX, QNX, …) Basic I/O statements and exchanges RAM/ROM Real time clock Disk drives Ethernet drives Display drives Hardware ... CPU 系统编程
编程语言的选择 • 考虑因素: • 应用领域; • 算法及运算的复杂性; • 软件运行的环境; • 系统性能要求; • 数据结构的复杂性; • 软件开发组成员对该语言的熟悉程度。
编程风格 • 程序必须是可以理解的 • 程序的风格应该强调简单和清晰 • 影响程序风格的因素有: • 源程序内部文档化; • 数据说明的方法; • 语句的结构; • I/O的方法。
源程序文档化 • 选择好标识符(变量和标号)的名字 • 挑选有意义的标识符名字 • 安排注解 • 序言式注解(头文件) • 功能注解 • 使程序的结构一目了然 • 缩进
数据说明 • 数据说明的次序应该规范化 • 多个变量说明时最好按字典序排列 • 对复杂结构用注解说明
语句结构 • 每个语句应该简单直接,不应该为提高效率而把语句复杂化 • 使程序简单易懂 • 避免采用复杂的条件语句 • 不要用“否定”条件的条件语句 • 避免多重的循环嵌套或条件嵌套 • 用括号使逻辑表达式或算术表达式更为清晰 • 用空格及有意义的符号使语句内容清晰明确 • 反问自己“如果这程序不是我编的,我能看懂吗?”
对批处理I/O 符合逻辑地组织输入 I/O出错检查 好的I/O出错恢复功能 清晰的输出报告格式 对交互式I/O 简单而有提示的输入方式 完备的出错处理及出错恢复 人机对话输出 I/O格式的一致性 原则: 检查所有输入数据的合法性 检查输入项的各种重要组合是否合理 输入格式要简单 最好采用数据结尾指示符,而不应要求用户规定“输入项目的数量” 交互式I/O要求用户输入时,标明交互输入可选择的种类和范围 输出时保持格式的一致性 设计和标明所有的输出 输入/输出
Wasserman交互系统设计原则 • 把计算机的内部特性掩盖起来不让用户看到 • 使程序“穿上防弹衣”,保证程序不被用户破坏 • 如果用户的请求会产生重大的后果,就要提醒用户 • 在用户使用程序时提供联机帮助 • 按照用户的水平设计输入要求 • 按照输出设备的速度设计输出信息 • 区别对待不同类型的用户 • 保持一致的响应时间 • 应尽量减少用户处理出错的工作量
效率 • 有效地利用临界资源,CPU和内存单元常被看作临界资源 • 有关效率的三个格言: • 效率是一种性能需求。软件的效率应根据需要,而不是尽可能地高! • 好的设计必然提高效率。 • 程序的简单性与程序的效率往往是一致的。 • 总之不要去牺牲程序的清晰性、可读性或正确性去追求效率非本质的提高
源程序的效率与算法效率直接相关 编程风格会影响运行速度及所需内存的大小 编译器的“优化”特性是提高效率的一种手段 原则: 在具体编程前应简化算术表达式及逻辑表达式 细心地分析多层嵌套循环以确定能否把一些语句或表达式移到循环之外 尽量避免采用多维数组 尽量避免采用指针及复杂的表 采用“快”的算术运算 不要把不同的数据类型混在一起 只要可能就采用整型数的算术运算和布尔表达式 源程序的效率
内存效率 • 大机器领域内存几乎无限制,虚存使“内存效率”不等同于“占用最小的内存” • 微机领域内存的限制仍是很现实的问题 • 采用汇编语言可以节省内存 • 提高运行效率的技术往往可以同时节省内存 • 使程序简单是提高内存效率的关键
输入输出效率 • 提高I/O效率的指导原则: • 全部I/O应有缓冲以避免过于频繁的信息交换 • 对外存应该选用最简单的可接收的存取方式 • 与外存联系的I/O操作应成块地传送数据 • 与终端及行式打印机联系的I/O操作应考虑设备的特性,以改进质量与速度 • 如果“超高效率”的I/O无法被人们理解,则是毫无意义的
好的程序设计风格的规则 • 写得清晰——而不是太灵巧 • 简单而直接地说明你的用意 • 使用库函数 • 避免使用临时变量 • 不要为了“效率”而牺牲清晰 • 让机器干苦活 • 用调用一个公共的子程序去代替重复的表示 • 选用不易混淆的变量名 • 避免使用不必要的转移
好的程序设计风格的规则 • 不使用条件转移代替一个逻辑表达式 • 假如一个逻辑表达式难以理解,则试着对其进行变换 • 使用数组,避免重复的控制序列 • 选用使程序简单的数据表示法 • 先用一个容易理解的伪语言写程序,然后再翻译成你所用的语言使用IF…ELSEIF…ELSEIF…ELSE…ENDIF实施多路选择 • 模块化,使用子程序
好的程序设计风格的规则 • 确保注释与代码一致 • 不要用注释去精确地重复代码——使每一个注释有价值 • 不要注释或修补坏代码——重写 • 使用有意义的变量名 • 使用有意义的语句标号 • 程序格式应有助于读者理解程序 • 为你的数据设计提供文档 • 仅使用GOTO去实施一个基本的结构
好的程序设计风格的规则 • 假如你能保持程序的可读性,则完全不必使用GOTO • 以小片段的方式写和测试一个大程序 • 对已定义的递归数据结构使用递归过程 • 检测输入的合理性和合法性 • 确保输入没有违反程序的限制 • 使用文件的结尾或标记终止输入,而不是用计数来终止输入 • 识别错误的输入(若有可能要恢复输入)
好的程序设计风格的规则 • 输入简易,输出自明 • 使用一致的输入格式 • 使输入容易校对 • 若可能,使用自由格式输入 • 使用自标识的输入,允许缺省,输出时反映这两者 • 确保在使用之前,所有变量已被置初值 • 在出现故障时不要死机 • 使用排错编译程序
好的程序设计风格的规则 • 用DATA语句或INITIAL属性置常数 • 用可执行的代码置变量初值 • 尽量注意由错误引起的分岔 • 注意在相等时转移的正确性 • 当一个循环从上边或底上退出到同一个地方时,必须十分小心 • 确保你的代码“没有做什么优美方面的事情” • 在边值处测试程序 • 人工核查某些答案
好的程序设计风格的规则 • 10.0乘以0.1很少是1.0 • 不要单独地进行浮点数相等比较 • 先保证正确,再提高速度 • 在提高速度之前,做好自动防止故障的措施 • 先保证清晰,再提高速度 • 不要为谋求“效率”上的少量增益而牺牲清晰 • 让你的编译程序做简单的优化 • 不要滥用再使用代码,取而代之的是改组 • 确保特殊情况是确实的特殊
好的程序设计风格的规则 • 保持简单,以提高速度 • 不要浪费代码而提高速度——找一个较好的算法 • 使用工具装备你的程序,在“效率”改变以前测量
程序编码结构要求 • 采用结构化编码方法 • 按以下22个特性构造
(1)完整性 • 任何程序或控制段的开始和结束,必须包含在单一的结构化模块中。
(2)功能 • 每个模块必须完成单一的定义良好的功能,模块的全部元素都是为了实现唯一的功能。 • 此外,模块实现的细节对其它模块来说应该是隐蔽的。如果实现的细节改变,直接受影响的只是实现功能的那个模块,并且只有该模块需要修改。
(3)入口/出口 • 每个模块一般要求单一入口和单一出口。处理完成后,模块必须返回到调用它的程序而不是其它模块。 • 接口(入口与出口条件和参数)必须明确表示和定义。
(4)说明 • 模块的说明语句和数据语句应放在程序首部之后和第一个可执行语句之前,虽然允许每行可有多个数据说明,但应保证清晰地定义复杂的数据结构。
(5)常量 • 常量必须在程序的说明中定义,常量通常有数组规模、π值、DO和FOR 循环中的循环数、数组下标、记录规模和行长度等。
(6)变元 • 在调用语句中的变元一般不得包含算术或逻辑表达式。 • 每个变元必须由单一变量来表示。 • 在调用一个模块的过程中,变元的类型和个数必须与模块的形参相一致。 • 此外,必须标明调用过程中使用的形参。
(7)幂 • 幂的指数必须用整数表示,即A**3而不是A**3.0。
(8)混合方式运算 • 应避免使用混合运算的算术表达式,不能避免时应仔细计算表达式的值,以保证类型转换得到预期的结果,应对转换进行适当的注释。
(9)转移 • 尽量少用无条件转移语句。如需使用,必须在同一程序单元内转移,并应向转移语句所在点的前方转移。 • 允许使用为实现结构化程序设计所必需的转移指令。
(10)错误处理 a.必须记录所有错误的发生及处理情况,保存系统发生错误的全部记录,以利于后续错误情况的处理和分析; b.必须预先了解错误的潜在影响,并且在它们出现之前确定如何处理; c.应尽可能使错误不扩散,不引起连锁反应; d.当程序不能执行时,必须在中止前释放已取得的全部资源和结果。
(11)范围检查 • 为保证变量值落在预期的范围内,必须进行范围检查。 • 如果变量值不在规定范围内,则必须进行适当的错误处理。 • 变量的定义域必须在设计时规定,在实现时声明,并在运行时检查。 • 必须进行范围检查的变量应包括:参数;数值下标;CASE结构中的变量参数;循环结构中用作初值、增量和终值的变量。
(12)序标和下标 • 循环序标参数和数值下标必须表示为整型的常量或变量。
(13)循环终止 • 必须保证循环终止,终止条件不能靠对循环参数所作假设的正确性,而是靠对循环入口事前直接的验证。
(14)标号和名字的使用 • 标号和名字必须有意义、一致并明显、唯一,不易混淆。
(15)全局变量和共享变量 • 应避免使用全局或共享变量。当一个变量由两个或多个模块共享时,每个模块都必须正确地使用该变量。 • 由多个模块使用的变量应作为变元进行通信。限制变量的范围有助于掌握变量的准确含义。 • 当有明确的技术根据需要使用公共数据时,应有下列限制: a.仅使用可由名字访问的公用域; b.公用数据域的长度和说明,对于使用它的每个模块都是相同的; c.可能时,应仅保留公用块的一个副本,而且必须用“INCLUDE ”语句包容在每一个模块中而不是在模块中各自编码描述。
(16)连接约定 • 如果模块是用汇编语言实现的,则必须定义和使用模块间通信的标准约定。目的是构造独立的、自包容的模块,它可以用良好定义的方法与其它模块通信。 • 应考虑的约定有: a.在将控制转给其它模块之前必须保护寄存器的内容,并在控制返回时恢复; b.通信必须通过变元素; c.必须有一个与调用模块返回地址进行通信的标准方法。
(17)输入与输出 • 输入例程和输出例程必须集中在有限几个模块内。 • 将这些例程汇集到少数几个模块中有利于输入和输出数据的监控。 • 此外,将这些例程限制在有限范围内可使修改更容易。
(18)命名 • 代码和数据单元的名字必须体现它们的功能和内容。
(19)程序首部 • 每个代码模块必须包含一个标准化的程序首部注释语句块,作为每个程序模块的内部源文档。它放在模块的首部,描述模块的功能、用途和操作要求。 • 程序首部应包括下面的信息: a.名称:包含用于标识模块的名称、版本标识符和入口。 b.目的:包含模块目的/功能的简要说明。
程序首部 • 程序首部应包括下面的信息: c.输入/输出,包含该模块所使用的每个I/O文件名,并指明是向模块输入、还是输出、还是两者兼有。使用交互式屏幕I/O的模块也应提供屏幕功能的说明。 d.参数:提供模块所需的全部变元的定义以及模块的返回值(输出参数)。参数定义必须包括:名字、数据类型、大小和功能。 e.调用:提供该模块调用的全部例程的清单和调用该模块的全部例程的清单。 f.全局数据:提供模块中使用的全部公用或全局数据的清单。
程序首部 • 程序首部应包括下面的信息: g.限制:包含约束或限制模块性能特点的任何特殊或非常规因素的清单。 h.异常结束:包含异常返回条件和动作的清单。 i.方法:包含为实现模块的功能而使用的方法的详细说明。 j.编程者:代码编制人名及所属机构。 k.版本号及完成日期:当前的模块版本号和它的完成日期。 l.修改记录:包含对该模块的修改人、所属机构、日期及对应的版本号。
(20)行间注释 • 源程序体内的注释必须解释程序执行的处理,必须指明每一个控制语句(有条件地更改一个数据值或语句的执行顺序的语句)的目的。 a.IF语句:说明条件满足时执行动作的理由。 b.I/O语句:标明处理的记录或文件的性质。 c.DO语句:说明执行动作的理由。 d.CALL语句:说明调用过程的理由。
(21)注释比例 • 注释行数不得少于源程序总行数的1/5。