第5章 编码
编码是软件设计的继续 编码的质量与软件设计的水平直接相关 但是,程序设计语言的特性和编码水平也会对程序的可靠性、可读性、可测试性等产生深远的影响 现代软件规模越来越大,软件结构更复杂,所使用的平台更加高级,因此将设计转化为代码的工作实际上也是非常庞大的 本章重点在于介绍编程过程中要牢记的一些软件工程的实践经验
5.1 程序设计语言 程序设计语言是人与计算机通信的最基本的工具 程序设计语言的特性会影响开发人员的思路和解决问题的方式,会影响代码的可理解性和可维护性 因此编码之前的一项重要工作就是选择一种适当的编程语言,但是,为一个软件项目选择适合的开发语言并不是简单的问题
程序设计语言
程序设计语言的演变 第一代语言:机器语言──硬件操作一一对应 第二代语言: 汇编语言──比机器语言直观。从软件工程角度,汇编语言只有在高级语言无法满足设计要求时,或者不支持某种特定应用的技术性能时,才被使用
程序设计语言 第三代语言:高级程序设计语言──使用的概念和符号与人们通常使用的概念和符号比较接近,它的一条语句往往对应若干条机器指令。又分为传统的基础语言、结构化程序语言和专用语言3类: 基础语言:历史悠久、应用广泛,有大量的函数库,代表有BASIC,FORTRAN,COBOL等 结构化语言:具有很强的过程控制能力和数据处理能力,并提供结构化的逻辑构造,代表有PL/1,PASCAL,C和Ada,都是从ALGOL语言派生的
程序设计语言 专用语言:是为特殊应用而设计的语言,通常具有特殊的语法形式,如: 应用于人工智能领域:LISP, Prolog 应用于数组和向量运算:APL 面向对象的开发语言:C++ 适于Internet环境开发:JAVA 第四代语言(4GL):抽象层次更高,不再涉及太多的算法性细节。目前使用最广的是数据库查询语言、程序代码生成器等。
程序设计语言 程序设计语言的特点 技术的观点: 涉及到从理论(形式语言理论)到实际(特定语言的性能)范围内的许多问题,一旦确定了软件需求,待选用的程序设计语言的技术特性就非常重要了。例如, 如果需要复杂的数据结构,就要仔细衡量有哪些语言能提供这些复杂的数据结构描述; 如果软件首要的是高性能及实时处理能力,就该选用适合于实时处理的语言,如C或汇编语言; 如果应用有许多输出报告或繁杂的文件处理,则可用Powerbuilder、Delphi或SQL。
程序设计语言 软件心理学的观点:从软件设计到程序代码的转换基本上都是手工进行的,因此编程语言的性能会对程序员的心理产生重大影响。从心理学观点,影响程序员心理的语言特性有: 二义性:引起程序员对程序理解的混乱 简洁性:程序员需要记忆的信息的总量 局部性:从语句到模块直至系统集成过程中实现模块的高内聚、低耦合的能力 一致性:采用的标记法的协调一致的程度 线性:语言的线性与维持功能域的概念紧密相连,如果存在大量的分支和循环,就会破坏线性状态,增加理解的难度
程序设计语言 软件工程的观点 详细设计能够直接地翻译成程序代码 源程序具有可移植性:对于可移植性是关键要求的软件,应严格遵守ISO或ANSI或GB的标准编写程序代码 编译程序应具有较高的效率:编译程序首先应该支持独立编译,并能够发现尽可能多的程序代码错误,辅助程序员提高程序调试效率 尽可能应用代码生成的自动工具 可维护性:对复杂的软件开发项目尤其重要,可维护性的前提是代码的可理解性。因此,源程序的可读性、语言的文档化特性是重要的因素
程序设计语言 程序设计语言的选择 项目的应用领域:例如PowerBuilder、Delphi等语言适合于IS的开发 编程人员的水平和编程经历 算法和计算复杂性:C/C++常用 数据结构的复杂性:PASCAL、JAVA的数据结构描述能力强大,FORTRAN、BASIC非常差 软件的开发成本和时间要求:如选择的语言很生僻,即使目前开发效率高,但以后维护工作量可能会很大 软件的可移植性要求:如果目标系统的运行环境不能确定(如WINDOWS、UNIX、OS/400),JAVA最好 可用的软件工具
5.2 程序设计风格 程序实际上也是一种供人阅读的文章,有一个文章的风格问题。应该使程序具有良好的风格。 源程序文档化 数据说明 语句结构 输入/输出方法
程序设计风格 :源程序文档化 标识符的命名 符号名即标识符,包括模块名、变量名、常量名、标号名、子程序名、 数据区名以及缓冲区名等。 这些名字应能反映它所代表的实际东西,应有一定实际意义。例如,表示次数的量用Times,表示总量的用Total,表示平均值的用Average等。 名字不是越长越好,应当选择精炼的意义明确的名字。必要时可使用缩写名字,但这时要注意缩写规则要一致,并且要给每一个名字加注释。同时,在一个程序中,一个变量只应用于一种用途。
程序设计风格 :源程序文档化 安排注释 夹在程序中的注释是程序员与日后的程序读者之间通信的重要手段。 注释绝不是可有可无的。 程序的注释 夹在程序中的注释是程序员与日后的程序读者之间通信的重要手段。 注释绝不是可有可无的。 一些正规的程序文本中,注释行的数量占到整个源程序的1/3到1/2,甚至更多。 注释分为序言性注释和功能性注释。
程序设计风格 :源程序文档化 序言性注释 通常置于每个程序模块的开头部分,它应当给出程序的整体说明,对于理解程序本身具有引导作用。有些软件开发部门对序言性注释做了明确而严格的规定,要求程序编制者逐项列出。 有关项目包括:
程序设计风格 :源程序文档化 程序标题 有关本模块功能和目的的说明; 主要算法; 接口说明:包括调用形式,参数描述,子程序清单; 有关数据描述:重要的变量及其用途,约束或限制条件,以及其它有关信息; 模块位置:在哪一个源文件中,或隶属于哪一个软件包; 开发简历:模块设计者,复审者,复审日期,修改日期及有关说明等。
程序设计风格 :源程序文档化 功能性注释 功能性注释嵌在源程序体中,用以描述其后的语句或程序段是在做什么工作,或是执行了下面的语句会怎么样。而不要解释下面怎么做。例如, /* ADD AMOUNT TO TOTAL */ TOTAL = AMOUNT+TOTAL 不好。
程序设计风格 :源程序文档化 如果注明把月销售额计入年度总额,便使读者理解了下面语句的意图: /* ADD MONTHLY-SALES TO ANNUAL-TOTAL */ TOTAL = AMOUNT+TOTAL 要点 描述一段程序,而不是每一个语句; 用缩进和空行,使程序与注释容易区别; 注释要正确。
程序设计风格 :源程序文档化 程序的视觉组织 恰当地利用空格,可以突出运算的优先性,避免发生运算的错误。 移行也叫做向右缩格。它是指程序中的各行不必都在左端对齐,都从第一格起排列。这样做使程序完全分不清层次关系。
程序设计风格 :源程序文档化 IF(…) THEN IF(…) THEN …… ELSE …… ENDIF …… ELSE …… ENDIF
程序设计风格 :数据说明 在设计阶段已经确定了数据结构的组织及其复杂性。在编写程序时,则需要注意数据说明的风格。 为了使程序中数据说明更易于理解和维护,必须注意以下几点。 数据说明的次序应当规范化
程序设计风格 :数据说明 例如,在程序中数据说明次序 ① 常量说明 ② 简单变量类型说明 ③ 数组说明 ④ 公用数据块说明 ⑤ 所有的文件说明 在类型说明中还可进一步要求。例如,可按如 下顺序排列: ① 整型量说明 ② 实型量说明 ③ 字符量说明 ④ 逻辑量说明
程序设计风格 :数据说明 说明语句中变量安排有序化 当多个变量名在一个说明语句中说明时,应当对这些变量按字母的顺序排列。 带标号的全程数据也应当按字母的顺序排列。 例如,把 integer size, length, width, cost, price 写成 integer cost, length, price , size, width
程序设计风格 :数据说明 如果设计了一个复杂的数据结构,应当使用注释来说明在程序实现时这个数据结构的固有特点。 使用注释说明复杂数据结构 如果设计了一个复杂的数据结构,应当使用注释来说明在程序实现时这个数据结构的固有特点。 例如, 对PL/1的链表结构和Pascal中用户自定义的数据类型,都应当在注释中做必要的补充说明。
程序设计风格 :语句结构 在设计阶段确定了软件的逻辑结构,但构造单个语句则是编码阶段的任务。语句构造力求简单,直接,不能为了片面追求效率而使语句复杂化。 在一行内只写一条语句 在一行内只写一条语句,并且采取适当的移行格式,使程序的逻辑和功能变得更加明确。 许多程序设计语言允许在一行内写多个语句。但这种方式会使程序可读性变差。因而不可取。
程序设计风格 :语句结构 例如,有一段排序程序 FOR I:=1 TO N-1 DO BEGIN T:=I;FOR J:=I+1 TO N DO IF A[J]<A[T] THEN T:=J;IF T≠I THEN BEGIN WORK:=A[T];A[T]:=A[I];A[I]:=WORK;END END; 由于一行中包括了多个语句,掩盖了程序的循环结构和条件结构,使其可读性变得很差。这段程序可以改进如下:
程序设计风格 :语句结构 FOR I:=1 TO N-1 DO //改进布局 BEGIN T:=I; FOR J:=I+1 TO N DO IF A[J]<A[T] THEN T:=J; IF T≠I THEN BEGIN WORK:=A[T]; A[T]:=A[I]; A[I]:=WORK; END END;
程序设计风格 :语句结构 程序编写首先应当考虑清晰性 程序编写首先应当考虑清晰性,不要刻意追求技巧性,使程序编写得过于紧凑。 例如,有一个用Pascal语句写出的程序段: A[I]:=A[I]+A[T]; A[T]:=A[I]-A[T]; A[I]:=A[I]-A[T];
程序设计风格 :语句结构 3. 程序要能直截了当地说明程序员的用意。 此段程序可能不易看懂,有时还需用实际数据试验一下。 实际上,这段程序的功能就是交换A[I]和A[T]中的内容。目的是为了节省一个工作单元。如果改一下: WORK:=A[T]; A[T]:=A[I]; A[I]:=WORK; 就能让读者一目了然了。 3. 程序要能直截了当地说明程序员的用意。
程序设计风格 :语句结构 A[I]+1/A[I]; 写成 AI=A[I]; X=AI+1/AI; 将一句分成两句写,会产生意想不到的问题。 避免使用临时变量而使可读性下降。 例如,有的程序员往往喜欢把表达式 A[I]+1/A[I]; 写成 AI=A[I]; X=AI+1/AI; 将一句分成两句写,会产生意想不到的问题。
程序设计风格 :语句结构 让编译程序做简单的优化。 尽可能使用库函数 避免不必要的转移。同时如果能保持程序可读性,则不必用 GO TO语句。 尽量只采用三种基本的控制结构来编写程序。
程序设计风格 :语句结构 可能产生二义性问题。 避免使用空的ELSE语句和IF… THEN IF…的语句。这种结构容 易使读者产生误解。 例如, IF ( CHAR>='A’ ) THEN IF ( CHAR<='Z’ ) THEN PRINT “This is a letter。” ELSE PRINT “This is not a letter。” 可能产生二义性问题。
程序设计风格 :语句结构 避免采用过于复杂的条件测试。 尽量减少使用“否定”条件的条件语句。 例如,如果在程序中出现 IF NOT ( ( CHAR<‘0’ ) OR ( CHAR>‘9’ ) ) THEN …… 改成 IF ( CHAR>='0’ ) AND ( CHAR<='9’ ) THEN …… 不要让读者绕弯子想。
程序设计风格 :语句结构 尽可能用通俗易懂的伪码来描述程序的流程,然后再翻译成必须使用的语言。 数据结构要有利于程序的简化。 要模块化,使模块功能尽可能单一化,模块间的耦合能够清晰可见。 利用信息隐蔽,确保每一个模块的独立性。
程序设计风格 :语句结构 从数据出发去构造程序。 不要修补不好的程序,要重新编写。也不要一味地追求代码的复用,要重新组织。 对太大的程序,要分块编写、测试,然后再集成。 ……
程序设计风格 :输入/输出方法 输入和输出信息是与用户的使用直接相关的。输入和输出的方式和格式应当尽可能方便用户的使用。一定要避免因设计不当给用户带来的麻烦。 因此,在软件需求分析阶段和设计阶段,就应基本确定输入和输出的风格。系统能否被用户接受,有时就取决于输入和输出的风格。
程序设计风格 :输入/输出方法 不论是批处理的输入/输出方式,还是交互式的输入/输出方式,在设计和程序编码时都应考虑下列原则: 对所有的输入数据都要进行检验,识别错误的输入,以保证每个数据的有效性; 检查输入项的各种重要组合的合理性,必要时报告输入状态信息; 使得输入的步骤和操作尽可能简单,并保持简单的输入格式;
程序设计风格 :输入/输出方法 输入数据时,应允许使用自由格式输入; 应允许缺省值; 输入一批数据时,最好使用输入结束标志,而不要由用户指定输入数据数目; 在交互式输入输入时,要在屏幕上使用提示符明确提示交互输入的请求,指明可使用选择项的种类和取值范围。同时,在数据输入的过程中和输入结束时,也要在屏幕上给出状态信息;
程序设计风格 :输入/输出方法 当程序设计语言对输入/输出格式有严格要求时,应保持输入格式与输入语句的要求的一致性; 给所有的输出加注解,并设计输出报表格式 输入/输出风格还受到许多其它因素的影响。如输入/输出设备(例如终端的类型,图形设备,数字化转换设备等)、用户的熟练程度、以及通信环境等。
5.3 程序设计标准 一个软件开发组织不管规模大小都要制定一套适用的编码规范,这个规范对于不同的项目可以调整。 可从以下方面制定编程规范: 标识符命名及书写规则 注释及格式要求 缩进规则 ……
程序设计标准 代码的功能; 代码的完成者; 代码在整个软件系统中的位置; 代码编制、复审的时间; 保留代码的原因; 必须将编程与编文档的工作统一起来: 既有利于整个项目按期完成,又能保证文档与程序协调一致。 一个程序段的文档包括: 代码的功能; 代码的完成者; 代码在整个软件系统中的位置; 代码编制、复审的时间; 保留代码的原因; 代码中如何使用数据结构和算法。