780 likes | 895 Views
软件制造工程. 第三章 编程工程. 本章主要内容. 编程工程的定义和内容 结构化编程 编码规范 编程前的准备 编程实施. 3.1.1 编程工程的定义和内容. 编程工程 就是用程序设计语言把程序设计的结果和过程翻译为在计算机相应环境下可运行的软件产品,把系统工程师按照用户需求设计出来的系统构架变为真正可运行的软件系统的工程。. 3.1.1 编程工程的定义. 编程工程的作业内容 详细地划分为制定工作标准,制定编码基准,理解设计书,程序编码,自查,送上级系统工程师审查,修改以及进行单元测试等若干步骤. 3.2 结构化编程.
E N D
软件制造工程 第三章 编程工程
本章主要内容 • 编程工程的定义和内容 • 结构化编程 • 编码规范 • 编程前的准备 • 编程实施
3.1.1 编程工程的定义和内容 • 编程工程就是用程序设计语言把程序设计的结果和过程翻译为在计算机相应环境下可运行的软件产品,把系统工程师按照用户需求设计出来的系统构架变为真正可运行的软件系统的工程。
3.1.1 编程工程的定义 • 编程工程的作业内容详细地划分为制定工作标准,制定编码基准,理解设计书,程序编码,自查,送上级系统工程师审查,修改以及进行单元测试等若干步骤.
3.2 结构化编程 • 结构化开发--结构化分析、结构化设计和结构化编程三个阶段
需求分析/ 验收测试计划 验收测试 结构化分析 外部设计/ 系统测试计划 系统测试 结构化设计 内部设计/ 组合测试计划 组合测试 结构化编程 程序制造 (编码&单元测试) 3.2.1 结构化开发过程
3.2.1 结构化开发过程 1、结构化分析 • 结构化分析方法的核心是沿数据流程图自顶向下、逐步求精,是最经典的面向数据流的需求分析方法。结构化分析方法使用系统流程图、数据流程图、数据字典、ER图、处理说明等工具来描述系统的功能需求、数据需求、运行需求和系统扩充需求。该方法广泛应用于银行,证券,商务处理,生产管理等大中型信息管理系统的需求分析过程。
3.2.1 结构化开发过程 • 在软件系统开发的初期阶段,首先要对用户的现行业务运行系统进行调查和现状分析,把握用户对新的开发系统的要求和希望,从用户提供的基本信息中,整理出开发系统目的和可能实现的功能范围,设计出新系统的数据流程图(DFD:Data Flow Diagram),显示屏幕关连图和功能概要说明书。
3.2.1 结构化开发过程 2、结构化设计 • 结构化设计方法通常也叫做面向数据流的设计、面向行为的设计。结构化设计方法是以需求分析阶段获得的新系统的数据流程图(DFD)和显示屏幕关连图为基础,通过一系列映射,自顶向下,逐步细化,把它们变换为具体的程序概要结构图和屏幕设计式样,把一个个复杂的问题分解细化为由多个功能模块组成的具有层次结构的软件系统。
3.2.1 结构化开发过程 3、结构化程序制造 • 结构化程序制造由结构化程序设计和结构化程序编码组成,它以外部设计和内部设计过程中获得的软件结构图及其相关设计资料为基础,采用自顶向下,逐步细化的方法,把一个个模块的功能逐步分解,细化为一系列具体的步骤,作出结构化程序设计说明书,程序员再按照程序设计说明书和系统设计的相关资料,把一步步的处理说明翻译成一系列用某种程序设计语言编写的程序代码。
3.2.2 结构化编码 • 程序代码的质量与软件系统外部设计和内部设计的质量直接相关,同时,程序设计语言的特性和程序员的编码水平,程序代码的可读性,可维护性,可靠性,可测试性都是直接影响程序质量的因素。
3.2.2 结构化编码 • 结构化编码采用自顶向下,逐步细化的方法,先全局,后局部,先整体,后细节,先抽象,后具体,逐步求精,编制出来的程序具有清晰的逻辑层次结构,容易阅读、理解、修改和维护,可以提高软件质量,提高软件开发的成功率和生产性。
结构化编码过程中,要遵循以下几个主要的原则:结构化编码过程中,要遵循以下几个主要的原则: ⑴ 尽可能使用语言提供的基本控制结构,顺序结构、选择结构和重复结构。 ⑵ 选用的控制结构只准许有一个入口和一个出口。 ⑶ 利用程序内部函数,把程序组织成容易识别的内部函数模块,每个模块只有一个入口或一个出口,一般不超过100行。 ⑷ 复杂结构应该用基本控制结构组合或嵌套来实现。 ⑸ 尽可能减少GOTO语句的使用,一般限制用到以下三种情况: • 把控制转移到出错处理。 • 把控制转移到函数模块结束 • 从深层嵌套的循环退出
3.2.2 结构化编码 • 大量采用GOTO语句实现控制路径,会使程序路径变得复杂而且混乱,但有时完全不用GOTO语句,可能会增加程序实现的复杂度。例如,在查找结束时、文件访问结束时或出现错误情况要从循环中转出时,使用GOTO语句会使程序更加清晰易懂。所以,应该加以限制地使用GOTO语句。
程序1 if ( A < B )goto 120;if ( B < C ) goto 110; 100 write ( C ); goto 140; 110 write ( B );goto 140; 120 if ( A < C ) goto 130; goto 100; 130 write ( A ); 140 end
程序2 if ( A < B ) and ( A < C ) then write ( A ) else if ( A B ) and ( B < C ) then write ( B ) else write ( C ) endif endif
3.2.3 结构化编码 • 在结构化程序的实现方法中,有两种常用的基本方法,第一是分类(BREAK)处理方法,第二是匹配(MATCHING)处理方法。
BREAK方法的引入:问题:根据学生成绩文件,统计各班的平均分,并输出到班级平均成绩文件中?BREAK方法的引入:问题:根据学生成绩文件,统计各班的平均分,并输出到班级平均成绩文件中?
程序处理过程(PDL代码): 读入学生成绩文件的第一个记录; beforeKey = 这个纪录的班级编号; sum =这个纪录的成绩; n = 1; While(学生成绩文件没有结束){ 读入下一个学生成绩记录; afterKey =这个纪录的班级编号; if (afterKey == beforeKey) { sum +=这个纪录的成绩; n++; } else { 输出sum/n到班级平均成绩文件; beforeKey = afterkey; sum =这个纪录的成绩; n=1; } } 输出sum/n到班级平均文件;
输入文件 BREAK处理 输出文件 Break方法处理概要
BREAK方法的前提条件: 在进行BREAK处理之前,输入文件必须是已经按照关键字项目值进行排序(升序或者降序)处理好的。
3.2.2 结构化编码 BREAK方法的处理流程说明: ① 按关键字项目值的升序读入输入文件的记录,把关键字项目的值存入工作变量中。 ② 关键字项目的值相同时,进行统计处理(或者其他处理)。 ③ 关键字项目的值发生了变化(BREAK)的时候,把变化前(BREAK BEFOR)的关键字项目值和统计结果输出到文件中(或者其他处理),用变化后(BREAK AFTER)的关键字项目值替换变化前的关键字项目值。
3.2.2 结构化编码 ④ 读入输入文件的下一条记录,把关键字项目的值存入变化后的工作变量中。 ⑤ 继续进行上述②至④的处理,直至文件读入结束。
MACHING方法的引入:问题:读入学生名称文件和学生成绩文件,把相同编号的数据记录结合起来,输出到学生成绩汇总文件中 ? 学生名称文件 学生成绩文件 汇总处理 学生成绩汇总文件
程序处理过程(PDL代码): 读入学生名称文件的第一个记录; bKey = 这个纪录的学号; 读入学生成绩文件的第一个记录; tKey = 这个纪录的学号; While(学生成绩文件没有结束){ if (bKey == tKey) { 输出bKey记录的学号、姓名和tKey记录的单科成绩和总成绩 到学生成绩汇总文件中; 读入下一个学生成绩记录; tKey = 这个纪录的学号; } else if (bKey < tKey) { 读入下一个学生名称记录; bKey = 这个纪录的学号; } else { 输出错误信息(学号为tKey的学生记录在学生名称文件中没有); 读入下一个学生成绩记录; tKey = 这个纪录的学号; } }
基础数据文件 事务数据文件 MATCHING处理 输出文件 错误信息文件 MACHING方法处理概要
3.2.2 结构化编码 • MATCHING方法的前提条件: 在进行MATCHING处理之前,输入文件必须是已经按照关键字项目的值进行排序(升序或者降序)处理好的。
3.2.2 结构化编码 • MATCHING方法处理流程说明: ① 按关键字项目值的升序读入基础文件的记录,把关键字项目的值存入基础KEY工作变量中。 ② 按关键字项目值的升序读入事务文件的记录,把关键字项目的值存入事务KEY工作变量中。 ③ 基础KEY的值与事务KEY值相等时,把事务文件的数据编辑输出到文件中。读入事务文件的下一条记录,把关键字值存入事务KEY。
3.2.2 结构化编码 ④ 基础KEY的值大于事务KEY值的时候,把事务KEY的值写到错误信息文件中。读入事务文件的下一条记录,把关键字值存入事务KEY。 ⑤ 基础KEY的值小于事务KEY值的时候,读入基础文件的下一条记录,把关键字值存入基础KEY。 ⑥ 继续进行上述③至⑤的处理,直至文件读入结束。
问题域 问题域 自然语言 需求分析 OOA (面向对象分析) 自然语言 分析与设计的鸿沟 总体设计 OOD (面向对象设计) 详细设计 OOP (面向对象编程) 面向对象的编程语言 编程语言 编程 OOT (面向对象测试) 测试 计算机 计算机 传统的软件工程方法与面向对象的软件工程方法
3.2.3 面向对象的编程 • 面向对象的编程语言 面向对象的编程语言(OOPL)与已往各种语言的根本不同是,它的设计出发点就是为了更直接地描述问题域中客观存在的事物(即对象)以及它们之间的关系,主要体现在以下几点: (1) 客观世界(问题域)是由一些具体的事物构成的。每个事物具有自己的静态特征(即可以由一组数据表示的特征)和动态特征(事物的行为或功能,即可以由一组操作表示的特征)。 OOPL用对象描述问题域中的事物,每个对象由一组属性和一组服务构成,分别描述事物的静态特征和动态特征。
3.2.3 面向对象的编程 ⑵ 客观世界中的事物既具有共同性又具有特殊性。人类认识客观世界的基本方法之一是对事物进行分类,即:根据事物的共同性把事物归结为某些类;考虑一个类中部分事物的特殊可得到这个类的子类,子类既具有父类的共同性又具有自己的特殊性。 OOPL用类表示一组具有相同的属性和服务的对象,并通过继承机制保证子类具有父类的全部属性和服务。
3.2.3 面向对象的编程 ⑶ 客观世界中较为复杂的事物往往是由其它一些比较简单的事物构成的,例如一架飞机由机舱、机翼和发动机构成。 OOPL中提供了描述这种组成关系的结构(一般—特殊结构、整体—部分结构等)。
3.2.3 面向对象的编程 (4) 客观世界中的一个事物可能与其它事物存在某种行为上的联系。例如:采购员购入一次货物要引起会计的一次帐目处理。 OOPL通过消息表示对象之间的动态联系。 面向对象的语言和人类认识、理解客观世界所使用的自然语言之间的距离是比较小的。
3.3 编码规范 • 代码组织与风格 • 注释 • 命名 • 声明
3.3.1 代码组织与风格 1 基本原则 • 代码的组织和风格的基本原则是:便于自己的开发,易于与他人的交流。 • 因个人习惯和编辑器等可以设置和形成自己的风格,但必须前后一致,并符合本规范的基本要求和原则。
3.3.1 代码组织与风格 2 缩进 • 子功能块当在其父功能块后缩进。 • 当功能块过多而导致缩进过深时将子功能块提取出来做为子函数。 • 代码中以TAB(4个字符)缩进,在编辑器中请将TAB设置为以空格替代,否则在不同编辑器或设置下会导致TAB长度不等而影响整个程序代码的格式。例如: 缩进示例: public void methodName(){ if(some condition){ for(…){ //some sentences }//end for }//end if }
3.3.1 代码组织与风格 3长度 • 为便于阅读和理解,单个函数的有效代码长度当尽量控制在100行以内(不包括注释行),当一个功能模块过大时往往造成阅读困难,因此当使用子函数等将相应功能抽取出来,这也有利于提高代码的重用度。 • 单个类也不宜过大,当出现此类情况时当将相应功能的代码重构到其他类中,通过组合等方式来调用,建议单个类的长度包括注释行不超过1500行。 • 尽量避免使用大类和长方法。
3.3.1 代码组织与风格 4行宽 页宽应该设置为80字符。一般不要超过这个宽度, 这会导致在某些机器中无法以一屏来完整显示, 但这一设置也可以灵活调整。在任何情况下, 超长的语句应该在一个逗号后或一个操作符前折行。一条语句折行后, 应该比原来的语句再缩进一个TAB或4个空格,以便于阅读。
3.3.1 代码组织与风格 5间隔 • 类、方法及功能块间等应以空行相隔,以增加可读性,但不得有无规则的大片空行。 • 操作符两端应当各空一个字符以增加可读性。 • 相应独立的功能模块之间可使用注释行间隔,并标明相应内容
3.3.1 代码组织与风格 6 对齐 • 关系密切的行应对齐,对齐包括类型、修饰、名称、参数等各部分对齐。 • 连续赋值时当对齐操作符。 • 当方法参数过多时当在每个参数后(逗号后)换行并对齐。 • 当控制或循环中的条件比较长时当换行(操作符前)、对齐并注释各条件。 • 变量定义最好通过添加空格形成对齐,同一类型的变量应放在一起 例
/*变量对齐-----------------------------------------------*/ 代码对齐和间隔示例 int count = 100; int length = 0; String strUserName = null; Integer[] porductCode = new Integer(2); //产品编码数组 /*参数对齐----------------------------------------------*/ public Connection getConnection(String url, String userName, String password) throws SQLException,IOException{ } /*换行对齐----------------------------------------------*/ public final static String SQL_SELECT_PRODUCT = “SELECT * “ + “ FROM TProduct WHERE Prod_ID = ” + prodID; /*条件对齐----------------------------------------------*/ if( Condition1 //当条件一 && Condition2 //并且条件二 || Condition3){ //或者条件三 } /*相应独立的功能模块之间可使用注释行间隔,并标明相应内容*/ for(int i = 0; i < productCount.length; //循环终止条件 i++){ }
3.3.1 代码组织与风格 7 括号 {} 中的语句应该单独作为一行,左括号"{"当紧跟其语句后,右括号"}"永远单独作为一行且与其匹配行对齐,并尽量在其后说明其匹配的功能模块。 较长的方法以及类、接口等的右括号后应使用//end ...等标识其结束。如: 类的结束符:}//EOC ClassName, 方法结束符:}//end methodName(), 功能块结束:}//end if...userName is null? 循环快结束:}//end for...every user in userList 左括号是否换行等随个人习惯而定,若换行则当与其前导语句首字符对齐。
3.3.2注释 • 注释分为序言性注释和功能性注释 • 功能性注释嵌在源程序体中,用以描述其后的语句或程序段是在做什么工作,或是执行了下面的语句会怎么样。而不要解释下面怎么做。 • 例如,/* ADD AMOUNT TO TOTAL */ TOTAL = AMOUNT+TOTAL不好。
如果注明把月销售额计入年度总额,便使读者理解了下面语句的意图:/* ADD MONTHLY-SALES TO ANNUAL-TOTAL */TOTAL = AMOUNT+TOTAL
3.3.2注释 1基本原则 (1) 注释应该增加代码的清晰度。代码注释的目的是要使代码更易于被其他开发人员等理解。 (2) 如果你的程序不值得注释,那么它很可能也不值得运行。 (3) 避免使用装饰性内容。 (4) 保持注释的简洁。 (5) 注释信息不仅要包括代码的功能,还应给出原因。 (6) 不要为注释而注释。 (7) 除变量定义等较短语句的注释可用行尾注释外,其他注释当避免使用行尾注释。
3.3.2注释 2文件注释 在每个文件的头部都应该包含该文件的功能、作用、作者、版权以及创建、修改记录等。
3.3.2注释 3类、接口注释 在类、接口定义之前当对其进行注释,包括类、接口的目的、作用、功能、继承于何种父类,实现的接口、实现的算法、使用方法、示例程序等。