文档库 最新最全的文档下载
当前位置:文档库 › 软件开发过程概述

软件开发过程概述

软件开发过程概述
软件开发过程概述

第1章软件开发过程概述

1.1 软件开发过程概述

1.1.1软件的概念

软件(Software)简单的说就是那些在计算机中能看的着,但摸不着的东西,概念性的说软件也称为“软设备”,广义地说软件是指系统中的程序以及开发、使用程序所需要的所有文档的集合软件分为系统软件和应用软件。

软件并不只是包括可以在计算机上运行的程序,与这些程序相关的文件一般也被认为是软件的一部分。

软件被应用于世界的各个领域,对人们的生活和工作都产生了深远的影响。

1. 系统软件

系统软件是负责管理计算机系统中各种独立的硬件,使得它们可以协调工作。系统软件使得计算机使用者和其他软件将计算机当作一个整体而不需要顾及到底层每个硬件是如何工作的。

一般来讲,系统软件包括操作系统和一系列基本的工具(比如编译器,数据库管理,存储器格式化,文件系统管理,用户身份验证,驱动管理,网络连接等方面的工具)。

2. 应用软件

应用软件是为了某种特定的用途而被开发的软件。它可以是一个特定的程序,比如一个图像浏览器。也可以是一组功能联系紧密,可以互相协作的程序的集合,比如微软的Office软件。也可以是一个由众多独立程序组成的庞大的软件系统,比如数据库管理系统。较常见的有:文字处理软件如WPS、Word等;信息管理软件;辅助设计软件如AutoCAD ;实时控制软件;教育与娱乐软件。

1.1.2编程与软件开发

软件开发的内容是:需求、设计、编程和测试。

(1)需求:不仅仅是用户需求,应该是开发中遇到的所有的需求。比如,你首先要知道做这个项目是为了解决什么问题;测试案例中应该输入什么数据......为了清楚地知道这些需求,你经常要和客户、项目经理等交流。

(2)设计:编码前,肯定有个计划告诉你要做什么,结构是怎样等等。你一定要按照这个来做,否则可能会一团糟。

(3)编程:如果在项目截止日,你的程序不能跑起来或达不到客户的要求,你就拿不到钱。

(4)测试:目的是让你知道,什么时候算是完成了。如果你聪明,你就应该先写测试,这样可以及时知道你是否真地完成了。否则,你经常会不知道,到底有哪些功能是真正完成了,离预期目标还差多远。

软件开发中,客户和开发人员都有自己的基本权利和义务。

(1)客户:

定义每个用户需求的商业优先级;

制订总体计划,包括用多少投资、经过多长时间、达到什么目的;

在项目开发过程中的每个工作周,都能让投资获得最大的收益;

通过重复运行你所指定的功能测试,准确地掌握项目进展情况;

能随时改变需求、功能或优先级,同时避免昂贵的再投资;能够根据各种变化及时调整项目计划;

能够随时取消项目;项目取消时,以前的开发工作不是一堆垃圾,已开发完的功能是合乎要求的,正在进行或未完成的的工作则应该是不难接手的。

(2)开发人员:

知道要做什么,以及要优先做什么;

工作有效率;

有问题或困难时,能得到客户、同事、上级的回答或帮助;

对工作做评估,并根据周围情况的变化及时重新评估;

积极承担工作,而不是消极接受分配。

1.1.3软件开发过程

软件开发过程一般分为以下6个阶段:

1. 计划

对所要解决的问题进行总体定义,包括了解用户的要求及现实环境,从技术、经济和社会因素等3个方面研究并论证本软件项目的可行性,编写可行性研究报告,探讨解决问题的方案,并对可供使用的资源(如计算机硬件、系统软件、人力等)成本,可取得的效益和开发进度作出估计。制订完成开发任务的实施计划。

2. 分析

软件需求分析就是回答做什么的问题。它是一个对用户的需求进行去粗取精、去伪存真、正确理解,然后把它用软件工程开发语言(形式功能规约,即需求规格说明书)表达出来的过程。本阶段的基本任务是和用户一起确定要解决的问题,建立软件的逻辑模型,编写需求规格说明书文档并最终得到用户的认可。需求分析的主要方法有结构化分析方法、数据流程图和数据字典等方法。本阶段的工作是根据需求说明书的要求,设计建立相应的软件系统的体系结构,并将整个系统分解成若干个子系统或模块,定义子系统或模块间的接口关系,对各子系统进行具体设计定义,编写软件概要设计和详细设计说明书,数据库或数据结构设计说明书,组装测试计划。

3. 设计

软件设计可以分为概要设计和详细设计两个阶段。实际上软件设计的主要任务就是将软件分解成模块是指能实现某个功能的数据和程序说明、可执行程序的程序单元。可以是一个函数、过程、子程序、一段带有程序说明的独立的程序和数据,也可以是可组合、可分解和可更换的功能单元。模块,然后进行模块设计。概要设计就是结构设计,其主要目标就是给出软件的模块结构,用软件结构图表示。详细设计的首要任务就是设计模块的程序流程、算法和数据结构,次要任务就是设计数据库,常用方法还是结构化程序设计方法。

4. 编码

软件编码是指把软件设计转换成计算机可以接受的程序,即写成以某一程序设计语言表示的"源程序清单"。充分了解软件开发语言、工具的特性和编程风格,有助于开发工具的选择以及保证软件产品的开发质量。

当前软件开发中除在专用场合,已经很少使用二十世纪80年代的高级语言了,取而代之的是面向对象的开发语言。而且面向对象的开发语言和开发环境大都合为一体,大大提高了开发的速度。

5. 测试

软件测试的目的是以较小的代价发现尽可能多的错误。要实现这个目标的关键在于设计一套出色的测试用例(测试数据和预期的输出结果组成了测试用例)。如何才能设计出一套出色的测试用例,关键在于理解测试方法。不同的测试方法有不同的测试用例设计方法。两种常用的测试方法是白盒法测试对象是源程序,依据的是程序内部的的逻辑结构来发现软件的编程错误、结构错误和数据错误。结构错误包括逻辑、数据流、初始化等错误。用例设计的关键是以较少的用例覆盖尽可能多的内部程序逻辑结果。白盒法和黑盒法依据的是软件的功能或软件行为描述,发现软件的接口、功能和结构错误。其中接口错误包括内部/外部接口、资源管理、集成化以及系统错误。黑盒法用例设计的关键同样也是以较少的用例覆盖模块输出和输入接口。黑盒法。

6. 维护

维护是旨在已完成对软件的研制(分析、设计、编码和测试)工作并交付使用以后,对软件产品所进行的一些软件工程的活动。即根据软件运行的情况,对软件进行适当修改,以适应新的要求,以及纠正运行中发现的错误。编写软件问题报告、软件修改报告。

一个中等规模的软件,如果研制阶段需要一年至二年的时间,在它投入使用以后,其运行或工作时间可能持续五年至十年。那么它的维护阶段也是运行的这五年至十年期间。在这段时间,人们几乎需要着手解决研制阶段所遇到的各种问题,同时还要解决某些维护工作本身特有的问题。做好软件维护工作,不仅能排除障碍,使软件能正常工作,而且还可以使它扩展功能,提高性能,为用户带来明显的经济效益。然而遗憾的是,对软件维护工作的重视往往远不如对软件研制工作的重视。而事实上,和软件研制工作相比,软件维

护的工作量和成本都要大得多。

在实际开发过程中,软件开发并不是从第一步进行到最后一步,而是在任何阶段,在进入下一阶段前一般都有一步或几步的回溯。在测试过程中的问题可能要求修改设计,用户可能会提出一些需要来修改需求说明书等。

1.2软件需求分析

1.2.1需求获取

需求获取(requirement elicitation)是需求工程的主体。对于所建议的软件产品,获取需求是一个确定和理解不同用户类的需要和限制的过程。获取用户需求位于软件需求三个层次的中间一层。业务需求决定用户需求,它描述了用户利用系统需要完成的任务。从这些任务中,分析者能获得用于描述系统活动的特定的软件功能需求,这些系统活动有助于用户执行他们的任务。

需求获取是在问题及其最终解决方案之间架设桥梁的第一步。获取需求的一个必不可少的结果是对项目中描述的客户需求的普遍理解。一旦理解了需求,分析者、开发者和客户就能探索出描述这些需求的多种解决方案。参与需求获取者只有在他们理解了问题之后才能开始设计系统,否则,对需求定义的任何改进,设计上都必须大量的返工。把需求获取集中在用户任务上—而不是集中在用户接口上—有助于防止开发组由于草率处理设计问题而造成的失误。

需求获取、分析、编写需求规格说明和验证并不遵循线性的顺序,这些活动是相互隔开、增量和反复的。当你和客户合作时,你就将会问一些问题,并且取得他们所提供的信息(需求获取)。同时,你将处理这些信息以理解它们,并把它们分成不同的类别,还要把客户需求同可能的软件需求相联系(分析)。然后,你可以使客户信息结构化,并编写成文档和示意图(说明)。下一步,就可以让客户代表评审文档并纠正存在的错误(验证)。这四个过程贯穿着需求分析的整个阶段。需求获取可能是软件开发中最困难、最关键、最易出错及最需要交流的方面。需求获取只有通过有效的客户—开发者的合作才能成功。分析者必须建立一个对问题进行彻底探讨的环境,而这些问题与产品有关。为了方便清晰地进行交流,就要列出重要的小组,而不是假想所有的参与者都持有相同的看法。对需求问题的全面考察需要一种技术,利用这种技术不但考虑了问题的功能需求方面,还可讨论项目的非功能需求。确定用户已经理解:对于某些功能的讨论并不意味着即将在产品中实现它。对于想到的需求必须集中处理并设定优先级,以避免一个不能带来任何益处的无限大的项目。

需求获取是一个需要高度合作的活动,而并不是客户所说的需求的简单誊本。作为一个分析者,你必须透过客户所提出的表面需求理解他们的真正需求。询问一个可扩充(open-ended)的问题有助于你更好地理解用户目前的业务过程并且知道新系统如何帮助或改进他们的工作。调查用户任务可能遇到的变更,或者用户需要使用系统其它可能的方式。想像你自己在学习用户的工作,你需要完成什么任务?你有什么问题?从这一角度来指导需求的开发和利用。

还有,探讨例外的情况:什么会妨碍用户顺利完成任务?对系统错误情况的反映,用户是如何想的?询问问题时,以“还有什么能”,”当?时,将会发生什么”“你有没有曾经想过”,“有没有人曾经”为开头。记下每一个需求的来源,这样向下跟踪直到发现特定的客户。

有些时候,尝试着问一些“愚蠢”的问题也有助于客户打开话匣子。如果你直接要求客户写出业务是如何实现的,客户十有八九无法完成。但是如果你尝试着问一些实际的问题,例如:“以我的理解,你们收到订单后,会...”。客户立刻就会指出你的错误,并滔滔不绝的开始谈论业务,而你,就在一边仔细的聆听吧。这一招就叫做“抛砖引玉”。

需求讨论会上必须要使用笔记本电脑,还要指定一个打字熟练的人把所有的讨论记录下来,记录的同时还要做一定的整理。如果不这样做,那么你结束会议的时候就会发现,所有的讨论只剩下一个模糊的印象,需求对你来说仍然是一件遥远的事情。在座谈讨论之后,记下所讨论的条目(item),并请参与讨论的用户评论并更正。及早并经常进行座谈讨论是需求获取成功的一个关键途径,因为只有提供需求的人才能确定是否真正获取需求。进行深入收集和分析以消除任何冲突或不一致性。

尽量把客户所持的假设解释清楚,特别是那些发生冲突的部分。从字里行间去理解以明确客户没有表达清楚但又想加入的特性或特征。Gause 和Weinberg(1989)提出使用“上下文无关问题”—这是一个高层次的问题,它可以获取业务问题和可能的解决方案的全部信息。客户对这些问题的回答诸如“产品要求怎样的精确度”或“你能帮我解释一下你为什么不同意某人的回答吗?”这些回答可以更直接地认识问题,而这是封闭(close-end)问题所不能做到的。

需求获取利用了所有可用的信息来源,这些信息描述了问题域或在软件解决方案中合理的特性。一个研究表明:比起不成功的项目,一个成功的项目在开发者和客户之间采用了更多的交流方式(Kiel and Carmel 1995)。与单个客户或潜在的用户组一起座谈,对于业务软件包或信息管理系统(MIS)的应用来说是一种传统的需求来源。直接聘请用户进行获取需求的过程是为项目获得支持和买入(buy-in)的一种方式。

尽量理解用户用于表述他们需求的思维过程。充分研究用户执行任务时作出决策的过程,并提取出潜在的逻辑关系。流程图和决策树是描述这些逻辑决策途径的好方法。

在需求获取的过程中,你可能会发现对项目范围的定义存在误差,不是太大就是太小。如果范围太大,你将要收集比真正需要更多的需求,以传递足够的业务和客户的值,此时获取过程将会拖延。如果项目范围太小,那么客户将会提出很重要的但又在当前产品范围之外的需求。当前的范围太小,以致不能提供一个令人满意的产品。需求的获取将导致修改项目的范围和任务,但作出这样具有深远影响的改变,一定要小心谨慎。

正如经常所说的,需求主要是关于系统做什么,而解决方案如何实现是属于设计的范围。这样说虽然很简洁,但似乎过于简单化。需求的获取应该把重点放在“做什么”上,但在分析和设计之间还是存在一定的距离。你可以使用假设“怎么做”来分类并改善你对用户需求的理解。在需求的获取过程中,分析模型、屏幕图形和原型可以使概念表达得更加清楚,然后提供一个寻找错误和遗漏的办法。把你在需求开发阶段所形成的模型和屏幕效果看成是方便高效交流的概念性建议,而不应该看成是对设计者选择的一种限制。

需求获取讨论会中如果参与者过多,就会减慢进度。人数大致控制在5到7人是最好的。这些人包括客户、系统设计者、开发者和可视化设计者等主要工程角色。相反地,从极少的代表那里收集信息或者只听到呼声最高、最有舆论影响的用户的声音,也会造成问题。这将导致忽视特定用户类的重要的需求,或者其需求不能代表绝大多数用户的需要。最好的权衡在于选择一些授权为他们的用户类发言的产品代表者,他们也被同组用户类的其它代表所支持。

1.2.2需求分析

1. 定义

所谓“需求分析”,是指对要解决的问题进行详细的分析,弄清楚问题的要求,包括需要输入什么数据,要得到什么结果,最后应输出什么。可以说,“需求分析”就是确定要计算机“做什么”。

在软件工程中,需求分析指的是在建立一个新的或改变一个现存的电脑系统时描写新系统的目的、范围、定义和功能时所要做的所有的工作。需求分析是软件工程中的一个关键过程。在这个过程中,系统分析员和软件工程师确定顾客的需要。只有在确定了这些需要后他们才能够分析和寻求新系统的解决方法。

在软件工程的历史中,很长时间里人们一直认为需求分析是整个软件工程中最简单的一个步骤,但在过去十年中越来越多的人认识到它是整个过程中最关键的一个过程。假如在需求分析时分析者们未能正确地认识到顾客的需要的话,那么最后的软件实际上不可能达到顾客的需要,或者软件无法在规定的时间里完工。

2. 特点

需求分析是一项重要的工作,也是最困难的工作。该阶段工作有以下特点:

(1)用户与开发人员很难进行交流

在软件生存周期中,其它四个阶段都是面向软件技术问题,只有本阶段是面向用户的。需求分析是对用户的业务活动进行分析,明确在用户的业务环境中软件系统应该"做什么"。但是在开始时,开发人员和用户双方都不能准确地提出系统要"做什么?"。因为软件开发人员不是用户问题领域的专家,不熟悉用户的业务活动和业务环境,又不可能在短期内搞清楚;而用户不熟悉计算机应用的有关问题。由于双方互相不了解对方的工作,又缺乏共同语言,所以在交流时存在着隔阂。

(2)用户的需求是动态变化的

对于一个大型而复杂的软件系统,用户很难精确完整地提出它的功能和性能要求。一开始只能提出一个大概、模糊的功能,只有经过长时间的反复认识才逐步明确。有时进入到设计、编程阶段才能明确,更有甚者,到开发后期还在提新的要求。这无疑给软件开发带来困难。

(3)系统变更的代价呈非线性增长

需求分析是软件开发的基础。假定在该阶段发现一个错误,解决它需要用一小时的时

间,到设计、编程、测试和维护阶段解决,则要花2.5、5、25、100倍的时间。

因此,对于大型复杂系统而言,首先要进行可行性研究。开发人员对用户的要求及现实环境进行调查、了解,从技术、经济和社会因素三个方面进行研究并论证该软件项目的可行性,根据可行性研究的结果,决定项目的取舍。

3. 任务

(1)确定对系统的综合要求

虽然功能需求是对软件系统的一项基本需求,但却并不是唯一的需求,通常对软件系统有下述几方面的综合要求。

a、功能需求

b、性能需求

c、可靠性和可用性需求

d、出错处理需求

e、接口需求

f、约束

g、逆向需求

h、将来可能提出的要求

(2)分析系统的数据要求

任何一个软件本质上都是信息处理系统,系统必须处理的信息和系统应该产生的信息很大程度上决定了系统的面貌,对软件设计有深远的影响,因此,必须分析系统的数据要求,这是软件分析的一个重要任务。分析系统的数据要求通常采用建立数据模型的方法。

复杂的数据由许多基本的数据元素组成,数据结构表示数据元素之间的逻辑关系。

利用数据字典可以全面地定义数据,但是数据字典的缺点是不够直观。为了提高可理解性,常常利用图形化工具辅助描述数据结构。用用的图形工具有层次方框图和Warnier 图。

(3)导出系统的逻辑模型

综合上述两项分析的结果可以导出系统的详细的逻辑模型,通常用数据流图、E-R图、状态转换图、数据字典和主要的处理算法描述这个逻辑模型。

(4)修正系统开发计划

根据在分析过程中获得的对系统的更深入的了解,可以比较准确地估计系统的成本和进度,修正以前定制的开发计划。

4. 方法

进行需求分析,应注意以下几点:

(1)首先调查组织机构情况

包括了解该组织的部门组成情况,各部门的职能等,为分析信息流程作准备。

(2)然后调查各部门的业务活动情况

包括了解各个部门输入和使用什么数据,如何加工处理这些数据,输出什么信息,输

出到什么部门,输出结果的格式是什么。

(3)协助用户明确对新系统的各种要求

包括信息要求、处理要求、完全性与完整性要求。

(4)确定新系统的边界

确定哪些功能由计算机完成或将来准备让计算机完成,哪些活动由人工完成。由计算机完成的功能就是新系统应该实现的功能。

需求分析常用的调查方法有:

(1)跟班作业

通过亲身参加业务工作来了解业务活动的情况。这种方法可以比较准确地理解用户的需求,但比较耗费时间。

(2)开调查会

通过与用户座谈来了解业务活动情况及用户需求。座谈时,参加者之间可以相互启发。

(3)请专人介绍。

(4)询问

对某些调查中的问题,可以找专人询问。

(5)设计调查表请用户填写

如果调查表设计得合理,这种方法是很有效,也很易于为用户接受的。

(6)查阅记录

即查阅与原系统有关的数据记录,包括原始单据、账簿、报表等。

通过调查了解了用户需求后,还需要进一步分析和表达用户的需求。

分析和表达用户需求的方法主要包括自顶向下和自底向上两类方法。

1.2.3需求文档的编写

需求的写作形式一般分为两种,面向对象和面向过程。对于不同的受众和应用,采取不同的形式。

面向过程的形式:

主要的思想是IPO的原则,也就是“输出-处理-输出”,文档格式:

(1)首先是对于整体系统的简略介绍:目的,确定文档描述的对象和大体内容

(2)系统上下文,介绍系统和其他系统之间的关系,边界如何划分

(3)系统的需求分解,介绍完成整体系统需要分解的大框架的需求内容

(4)具体需求

对于具体需求很简单,按照如下形式完成:

a、简介

b、输入

c、处理

d、输出

(5)除了具体需求外,还包括其他相关方面的需求:

a、接口需求(与其他系统、子系统、模块的接口,用户接口等)所谓的界面原型,其

实是接口需求中的内容。由于界面原型通常都很重要,所以可以将这一部分拿出来放到具体需求中去。

界面原型不是仅仅一张图,还包括界面元素的描述、范围、错误提示信息等

b、性能需求

c、依赖:依赖的数据库、第三方软件等

d、需求优先级排序,用于衡量开发策略

(6)参考文档

面向对象的形式,整体文档架构是和上面描述的一致,区别只有两点。

(1)在系统的需求分解处,用用例的包图来描述、这个很简单,其实就是上面文字描述的图形化显示。

(2)主要区别是具体需求,通过用例的形式来描述,包括:

a、介绍

b、用户(actor)

c、前置条件

d、后置条件

e、触发条件

f、事件流

g、备选事件流

1.3软件系统架构设计

软件架构(software architecture)是一系列相关的抽象模式,用于指导大型软件系统各个方面的设计。软件架构是一个系统的草图。软件架构描述的对象是直接构成系统的抽象组件。各个组件之间的连接则明确和相对细致地描述组件之间的通讯。在实现阶段,这些抽象组件被细化为实际的组件,比如具体某个类或者对象。在面向对象领域中,组件之间的连接通常用接口_(计算机科学)来实现。

软件体系结构是构建计算机软件实践的基础。与建筑师设定建筑项目的设计原则和目标,作为绘图员画图的基础一样,一个软件架构师或者系统架构师陈述软件构架以作为满足不同客户需求的实际系统设计方案的基础。

软件构架是一个容易理解的概念,多数工程师(尤其是经验不多的工程师)会从直觉上来认识它,但要给出精确的定义很困难。特别是,很难明确地区分设计和构架:构架属于设计的一方面,它集中于某些具体的特征。

在“软件构架简介”中,David GArlan 和Mary Shaw 认为软件构架是有关如下问题的设计层次:“在计算的算法和数据结构之外,设计并确定系统整体结构成为了新的问题。结构问题包括总体组织结构和全局控制结构;通信、同步和数据访问的协议;设计元素的功能分配;物理分布;设计元素的组成;定标与性能;备选设计的选择。”

但构架不仅是结构;IEEE Working Group on Architecture 把其定义为“系统在其环境中的最高层概念”。构架还包括“符合”系统完整性、经济约束条件、审美需求和样式。它并不仅注重对内部的考虑,而且还在系统的用户环境和开发环境中对系统进行整体考虑,即

同时注重对外部的考虑。

在Rational Unified ProcESs 中,软件系统的构架(在某一给定点)是指系统重要构件的组织或结构,这些重要构件通过接口与不断减小的构件与接口所组成的构件进行交互。

从和目的、主题、材料和结构的联系上来说,软件架构可以和建筑物的架构相比拟。一个软件架构师需要有广泛的软件理论知识和相应的经验来事实和管理软件产品的高级设计。软件架构师定义和设计软件的模块化,模块之间的交互,用户界面风格,对外接口方法,创新的设计特性,以及高层事物的对象操作、逻辑和流程。

1.3.1 软件架构的要素

一般而言,软件系统的架构(ArchitECture)有两个要素:

(1)它是一个软件系统从整体到部分的最高层次的划分。

一个系统通常是由元件组成的,而这些元件如何形成、相互之间如何发生作用,则是关于这个系统本身结构的重要信息。

详细地说,就是要包括架构元件(Architecture Component)、联结器(Connector)、任务流(TASk-flow)。所谓架构元素,也就是组成系统的核心"砖瓦",而联结器则描述这些元件之间通讯的路径、通讯的机制、通讯的预期结果,任务流则描述系统如何使用这些元件和联结器完成某一项需求。

(2)建造一个系统所作出的最高层次的、以后难以更改的,商业的和技术的决定。

在建造一个系统之前会有很多的重要决定需要事先作出,而一旦系统开始进行详细设计甚至建造,这些决定就很难更改甚至无法更改。显然,这样的决定必定是有关系统设计成败的最重要决定,必须经过非常慎重的研究和考察。

1.3.2 软件架构的目标

正如同软件本身有其要达到的目标一样,架构设计要达到的目标是什么呢?一般而言,软件架构设计要达到如下的目标:

(1)可靠性(Reliable)。软件系统对于用户的商业经营和管理来说极为重要,因此软件系统必须非常可靠。

(2)安全行(Secure)。软件系统所承担的交易的商业价值极高,系统的安全性非常重要。

(3)可扩展性(SCAlable)。软件必须能够在用户的使用率、用户的数目增加很快的情况下,保持合理的性能。只有这样,才能适应用户的市场扩展得可能性。

(4)可定制化(CuSTomizable)。同样的一套软件,可以根据客户群的不同和市场需求的变化进行调整。

(5)可扩展性(Extensible)。在新技术出现的时候,一个软件系统应当允许导入新技术,从而对现有系统进行功能和性能的扩展。

(6)可维护性(MAIntainable)。软件系统的维护包括两方面,一是排除现有的错误,二是将新的软件需求反映到现有系统中去。一个易于维护的系统可以有效地降低技术支持的花费。

(7)客户体验(Customer Experience)。软件系统必须易于使用。

(8)市场时机(Time to Market)。软件用户要面临同业竞争,软件提供商也要面临同业竞争。以最快的速度争夺市场先机非常重要。

1.3.3 软件架构的种类

根据我们关注的角度不同,可以将架构分成三种:

(1)逻辑架构、软件系统中元件之间的关系,比如用户界面,数据库,外部系统接口,商业逻辑元件,等等。

(2)物理架构、软件元件是怎样放到硬件上的。

(3)系统架构、系统的非功能性特征,如可扩展性、可靠性、强壮性、灵活性、性能等。

系统架构的设计要求架构师具备软件和硬件的功能和性能的过硬知识,这一工作无疑是架构设计工作中最为困难的工作。

此外,从每一个角度上看,都可以看到架构的两要素:元件划分和设计决定。

首先,一个软件系统中的元件首先是逻辑元件。这些逻辑元件如何放到硬件上,以及这些元件如何为整个系统的可扩展性、可靠性、强壮性、灵活性、性能等做出贡献,是非常重要的信息。

其次,进行软件设计需要做出的决定中,必然会包括逻辑结构、物理结构,以及它们如何影响到系统的所有非功能性特征。这些决定中会有很多是一旦作出,就很难更改的。

根据作者的经验,一个基于数据库的系统架构,有多少个数据表,就会有多少页的架构设计文档。比如一个中等的数据库应用系统通常含有一百个左右的数据表,这样的一个系统设计通常需要有一百页左右的架构设计文档。

1.3.4 软件构架的描述

为了讨论和分析软件构架,必须首先定义构架表示方式,即描述构架重要方面的方式。在Rational Unified Process 中,软件构架文档记录有这种描述。

(1)构架视图

我们决定以多种构架视图来表示软件构架。每种构架视图针对于开发流程中的涉众(例如最终用户、设计人员、管理人员、系统工程师、维护人员等)所关注的特定方面。

构架视图显示了软件构架如何分解为构件,以及构件如何由连接器连接来产生有用的形式,由此记录主要的结构设计决策。这些设计决策必须基于需求以及功能、补充和其他方面的约束。而这些决策又会在较低层次上为需求和将来的设计决策施加进一步的约束。

(2)典型的构架视图集

构架由许多不同的构架视图来表示,这些视图本质上是以图形方式来摘要说明“在构架方面具有重要意义”的模型元素。在Rational Unified Process 中,您将从一个典型的视图集开始,该视图集称为“4+1 视图模型”。它包括:

用例视图:包括用例和场景,这些用例和场景包括在构架方面具有重要意义的行为、类或技术风险。它是用例模型的子集。逻辑视图:包括最重要的设计类、从这些设计类到

包和子系统的组织形式,以及从这些包和子系统到层的组织形式。它还包括一些用例实现。它是设计模型的子集。实施视图:包括实施模型及其从模块到包和层的组织形式的概览。同时还描述了将逻辑视图中的包和类向实施视图中的包和模块分配的情况。它是实施模型的子集。进程视图:包括所涉及任务(进程和线程)的描述,它们的交互和配置,以及将设计对象和类向任务的分配情况。只有在系统具有很高程度的并行时,才需要该视图。在Rational Unified Process 中,它是设计模型的子集。配置视图:包括对最典型的平台配置的各种物理节点的描述以及将任务(来自进程视图)向物理节点分配的情况。只有在分布式系统中才需要该视图。它是部署模型的一个子集。构架视图记录在软件构架文档中。您可以构建其他视图来表达需要特别关注的不同方面:用户界面视图、安全视图、数据视图等等。对于简单系统,可以省略4+1视图模型中的一些视图。

1.3.5 软件架构师

软体设计师中有一些技术水平较高、经验较为丰富的人,他们需要承担软件系统的架构设计,也就是需要设计系统的元件如何划分、元件之间如何发生相互作用,以及系统中逻辑的、物理的、系统的重要决定的作出。

这样的人就是所谓的架构师(Architect)。在很多公司中,架构师不是一个专门的和正式的职务。通常在一个开发小组中,最有经验的程序员会负责一些架构方面的工作。在一个部门中,最有经验的项目经理会负责一些架构方面的工作。

但是,越来越多的公司体认到架构工作的重要性,并且在不同的组织层次上设置专门的架构师位置,由他们负责不同层次上的逻辑架构、物理架构、系统架构的设计、配置、维护等工作。

1.4软件详细设计

软件详细设计的任务是,是为软件结构图中的每个模块确定所采用的算法和块内数据结构,用某种选定的表达工具给出清晰的描述,表达工具可以自由选择,但工具必须具有描述过程细节的能力,而且能够有利于程序员在编程时便于直接翻译成程序设计语言的源程序。

程序流程图、盒图、PAD图、HIPU图、PDL语言等等都是完成详细设计的工具,选择合适的工具并且正确地使用是十分重要的。面向数据结构设计方法(Jackson方法)是进行详细设计的形式化方法。

在软件详细设计阶段,将生成详细设计说明书,为每个模块确定采用的算法,确定每个模块使用的数据结构,确定每个模块的接口细节。在软件详细设计结束时,软件详细设计说明书通过复审的形成形成正式文档,作为下一个阶段的工作依据。

在概要设计阶段,已经确定了软件系统的总体结构,给出了软件系统中各个组成模块的功能和模块间的接口。作为软件设计的饿第二步,软件详细设计就是在软件概要设计的基础上,考虑如何实现定义的软件系统,直到对系统中的每个模块给出了足够详细的过程描述。在软件详细设计以后,程序员将仍旧根据详细设计的过程编写出实际的程序代码。因此,软件详细设计的结果基本上决定了最终的程序代码质量。

1.5软件编码

1.5.1软件开发语言及工具的选择

程序编码阶段的任务是将软件的详细设计转换成用程序设计语言实现的程序代码。因此,程序设计语言的性能和设计风格对于程序设计的效能和质量有着直接的关系。

1. 程序设计语言特性的比较

a、软件心理学的观点

因为从设计到编码的转换基本上是人的活动,因此语言的性能对程序员的心理影响,将对转换产生重大影响。程序员总是希望选择简单易学、使用方便的语言,以减少程序出错率,提高软件可靠性。从心理学的观点,影响程序员心理的语言特性有如下6种:·一致性:它表示一种语言所使用符号的兼容程度、允许随意规定限制、以及允许对语法或语义破例的程度。同是一个符号,给予多种用途,会引起许多难以察觉的错误。

·二义性:虽然语言的编译程序总是以一种机械的规则来解释语句,但读者则可能用不同的方式来理解语句。例如,对于一个逻辑表达式A≥“0”and A≤“9”,读者可能对这个逻辑表达式有不同的理解。

如果一个程序设计语言缺乏一致性和存在二义性,那么用这种语言编写出来的程序可读性就差,同时用这种语言编程也容易出错。

·简洁性(紧凑性):表示程序员为了用该语言编写程序,必须记忆的有关编码的信息量。可用语言支持块结构和结构化程序的能力、可使用的保留字和缩写字的种类、数据类型的种类和缺省说明、算术运算符和逻辑运算符的种类、系统内标准函数的数目等来衡量。

遗憾的是,语言的简洁性与程序的一致性常常是抵触的。

·局部性:指程序设计语言的联想(综合)特性。综合的特性使人们能够对事物从整体上进行记忆和识别。在编码过程中,由语句组合成模块,由模块组装为程序体系结构,并在组装过程中实现模块的高内聚和低耦合,可使程序的局部性加强。

·线性:指程序的联想(顺序)特性。人们总是习惯于按逻辑线性序列理解程序。如果程序中线性序列和逻辑运算较多,会提高可读性。如果存在大量的分支和循环,就会破坏顺序状态,增加理解上的困难。直接实现结构化程序可提高程序的线性特性。

·传统:人们学习一种新的程序设计语言的能力受到传统的影响。具有Pascal 基础的程序人员在学习C 语言时不会感到困难,因为C保持了Pascal 所确立的传统语言特性。但是要求同一个人去学习APL或者LISP这样一些语言,传统就中断了。

b、软件工程的观点

从软件工程观点,程序设计语言的特性应着重考虑软件开发项目的需要。为此,对于程序编码,有如下一些工程上的性能要求:

·详细设计应能直接地容易地翻译成代码程序:把设计变为程序的难易程度,反映了程序设计语言与设计说明相接近的程度。所选择的程序设计语言是否具有结构化的构造,复杂的数据结构,专门的输入/输出能力,位运算和串处理的能力,直接影响到从详细设

计变换到代码程序的难易程度,以及特定软件开发项目的可实现性。

·源程序应具有可移植性:源程序的可移植性通常有三种解释:①对源程序不做修改或少做修改就可以实现处理机上的移植或编译程序上的移植;②即使程序的运行环境改变(例如,改用一个新版本的操作系统),源程序也不用改变;③源程序的许多模块可以不做修改或少做修改就能集成为功能性的各种软件包,以适应不同的需要。

为改善软件的可移植性,主要是使语言标准化。在开发软件时,应严格地遵守ISO或ANSI、GB的标准,而不要去理会特定编译器提供的非标准特性。

·编译程序应具有较高的效率。

·尽可能应用代码生成的自动工具:有效的软件开发工具是缩短编码时间,改善源代码质量的关键因素。使用带有各种有效的自动化工具的“软件开发环境”,支持从设计到源代码的翻译等各项工作,可以保证软件开发获得成功。

·可维护性:源程序的可读性,语言自身的文档化特性(涉及标识符的允许长度、标号命名、数据类型的丰富程度、控制结构的规定等)是影响到可维护性的重要因素。

c、程序设计语言的技术性能

在计划阶段,极少考虑程序语言的技术特性。但在选定资源时,要规划将要使用的支撑工具,就要确定一个具体的编译器或者确定一个程序设计环境。如果软件开发组的成员对所要使用的语言不熟悉,那么在成本及进度估算时必须把学习的工作量估算在内。

一旦确定了软件需求,待选用的程序语言的技术特性就显得非常重要了。如果需要复杂的数据结构,就要仔细衡量有哪些语言能提供这些复杂的数据结构。如果首要的是高性能及实时处理的能力,就可选用适合于实时应用的语言或效率高的语言。如果该应用有许多输出报告或繁杂的文件处理,最好是根据软件的要求,选定一种适合于该项工作的语言。

软件的设计质量与程序设计语言的技术性能无关(面向对象设计例外)。但在实现软件设计转化为程序代码时,转化的质量往往受语言性能的影响。因而也会影响到设计方法。

语言的技术性能对测试和维护的影响是多种多样的。例如,直接提供结构化构造的语言有利于减少循环带来的复杂性(即McCabe复杂性),使程序易读、易测试、易维护。另一方面,语言的某些技术特性却会妨碍测试。例如,在面向对象的语言程序中,由于实行了数据封装,使得监控这些数据的执行状态变得比较困难;由于建立了对象类的继承结构,使得高内聚、低耦合的要求受到破坏,增加了测试的困难。此外,只要语言程序的可读性强,而且可以减少程序的复杂性,这样的程序设计语言对于软件的维护就是有利的。

总之,通过仔细地分析和比较,选择一种功能强而又适用的语言,对成功地实现从软件设计到编码的转换,提高软件的质量,改善软件的可测试性和可维护性是至关重要的。

2. 程序设计语言的分类

目前,用于软件开发的程序设计语言已经有数百种之多,对这些程序设计语言的分类有不少争议。同一种语言可以归到不同的类中。从软件工程的角度,根据程序设计语言发展的历程,可以把它们大致分为4类。

b、从属于机器的语言(第一代语言)

它是由机器指令代码组成的语言。对于不同的机器就有相应的一套机器语言。用这种

语言编写的程序,都是二进制代码的形式,且所有的地址分配都是以绝对地址的形式处理。存储空间的安排,寄存器、变址的使用都由程序员自己计划。因此使用机器语言编写的程序很不直观,在计算机内的运行效率很高但编写出的机器语言程序其出错率也高。

b、汇编语言(第二代语言)

汇编语言比机器语言直观,它的每一条符号指令与相应的机器指令有对应关系,同时又增加了一些诸如宏、符号地址等功能。存储空间的安排可由机器解决。不同指令集的处理器系统就有自己相应的汇编语言。从软件工程的角度来看,汇编语言只是在高级语言无法满足设计要求时,或者不具备支持某种特定功能(例如特殊的输入/输出)的技术性能时,才被使用。

c、高级程序设计语言(第三代语言)

·传统的高级程序设计语言:如FORTRAN、COBOL、ALGOL、BASIC等。这些程序语言曾得到广泛应用。目前,它们都已有多种版本。有的语言得到较大的改进,甚至形成了可视的开发环境,具有图形设计工具、结构化的事件驱动编程模式、开放的环境,使用户可以既快又简便地编制出windows下的各种应用程序。

·通用的结构化程序设计语言:它具有很强的过程功能和数据结构功能,并提供结构化的逻辑构造。这一类语言的代表是PL/1,PASCAL,C和Ada。此外,COBOL78、Turbo BASIC等也应归入第三代程序语言范围。

·专用语言:专用语言是为特殊的应用而设计的语言。通常具有自己特殊的语法形式,面对特定的问题,输入结构及词汇表与该问题的相应范围密切相关。有代表性的专用语言有APL 、Lisp、PROLOG 、Smalltalk、C++、FORTH等。从软件工程的角度来看,专用语言支持了特殊的应用,将特定的设计要求翻译成可执行的代码。但是它们的可移植性和可维护性比较差。

d、第四代语言(4GL)

4GL 用不同的文法表示程序结构和数据结构,但是它是在更高一级抽象的层次上表示这些结构,它不再需要规定算法的细节。4GL 兼有过程性和非过程性的两重特性。程序员规定条件和相应的动作这是过程性的部分,并且指出想要的结果,这是非过程部分。然后由4GL语言系统运用它的专门领域的知识来填充过程细节。

Martin把第四代语言分为以下几种类型:

·查询语言:用户可利用查询语言对预先定义在数据库中的信息进行较复杂的操作。

·程序生成器:只需很少的语句就能生成完整的第三代语言程序,它不必依赖预先定义的数据库作为它的着手点。

·其它4GL:如判定支持语言、原型语言、形式化规格说明语言等。

3. 程序设计语言的选择

为某个特定开发项目选择程序设计语言时,既要从技术角度、工程角度、心理学角度评价和比较各种语言的适用程度,又必须考虑现实可能性。有时需要作出某种合理的折衷。

在选择与评价语言时,首先要从问题入手,确定它的要求是什么?这些要求的相对重要性如何?再根据这些要求和相对重要性来衡量能采用的语言。

通常考虑的因素有:①项目的应用范围;②算法和计算复杂性;③软件执行的环境;

④性能上的考虑与实现的条件;⑤数据结构的复杂性;⑥软件开发人员的知识水平和心理因素等。其中,项目的应用范围是最关键的因素。

针对计算机的4个主要应用领域,为语言做一个粗略的分类。例如,在科学与工程计算领域内,C,C++ 语言得到了广泛的应用,但FORTRAN仍然是应用最广泛的语言。在商业数据处理领域中,通常采用COBOL,RPG语言编写程序,当然也可选用SQL 语言或其它专用语言。在系统程序设计和实时应用领域中,汇编语言或一些新的派生语言,如BLISS,PL/S,Ada,C++等得到了广泛的应用。在人工智能领域以及问题求解,组合应用领域,主要采用LISP和PROLOG语言。

新的更强有力的语言,虽然对于应用有很强的吸引力,但是因为已有的语言已经积累了大量的久经使用的程序,具有完整的资料、支撑软件和软件开发工具,程序设计人员比较熟悉,而且有过类似项目的开发经验和成功的先例,由于心理因素,人们往往宁愿选用原有的语种。所以应当彻底地分析,评价,介绍新的语言,以便从原有语言过渡到新的语言。

1.5.2编码规范与编程风格

编写代码时,保持良好的编码习惯是十分重要的,这样写出的代码既能被编译器正确地识别,又能增强程序的可读性和可维护性。一般来说,不同的编程语言的编码规则是不相同的,下面介绍编写Visual C# 2005程序时应当遵循的一些规则。

1. 分号与分行

C# 语句使用“;”结束,即编译器遇到“;”便认为该条语句结束,因此编写代码时可以在一行中编写多条C# 语句。然而并不提倡这么做,一行中只编写一条语句可以让代码的结构更清晰,从而提高其可读性和可维护性。

当一条语句太长,不适合单行显示时,可以分成多行来编写。但分行时不能随意,应当遵循下面的原则:

(1)在一个逗号后换行。

(2)在一个操作符后换行。

(3)在表达式的高层次处换行。

(4)新行与前一行在同一层次,并与表达式的起始对齐。

下面看两个分行例子:

//************************************************************************************* boolYear = (year % 4 == 0 && year % 100 != 0)

|| (year % 400 == 0);

num = a * b / (c – d + e)

+ 4 * f;

//************************************************************************************* 上面的分行方法是不错的,在表达式的“)”号后面开始分行,显得结构清晰,容易读懂,是值得提倡的做法。

再看下面的分行例子:

//************************************************************************************* boolYear = (year % 4 == 0 && year % 100 != 0)|| (year

% 400 == 0);

num = a * b / (c - d

+ e) + 4 * f;

//************************************************************************************* 显然这样的分行是难于被人接受的,它违背了分行的高层次规则,在编程的过程中,应当避免这样做。

2. 注释

注释是编写程序代码时不可缺少的,经验表明:成熟的源代码中包含三分之一到二分之一的注释。这样,可以提高程序的可读性,方便对源代码的阅读和修改。因此,在程序适当的位置加上注释语句是一种良好的编码习惯。

(1)行注释

C# 中的行注释(即注释内容写在同一行)通常用来注释掉一行代码,也可以用它注释掉代码块。当然也可以作为代码的单行解释且单独成一行时,书写行注释时必须要将其缩进到与代码对齐。

行注释的格式如下:

// <注释内容>

例如:

// 下面代码定义一个整型变量maxNum

int maxNum;

或者:

int maxNum; // 定义一个整型变量maxNum

(2)块注释

C# 中的块注释(即多行注释,注释内容写在多个代码行)通常用来注释掉一个代码块,当然也可以作为代码的解释。编码时,通常要尽量避免使用块注释。实际上块注释是很少使用到的,一般仅在需要注释掉一段代码或注释内容很多时使用。

Visual C# 2005中的块注释格式如下:

/*

<注释第1行>

<注释第2行>

<注释第3行>

……

*/

例如下面是自定义方法maxNum方法的注释:

/************************************************************************************* 方法名:maxNum

方法的参数:两个整型参数

方法功能:求两个数中的最大者

方法返回值的数据类型:整型数据

创建日期:2007-8-25

*************************************************************************************/ < maxNum方法源代码>

3. 空格、空行与括号

在代码中合理地加入空格、空行以及人为添加一些括号是一位优秀的程序员所必须做到的,这样可以很大程度上提高编程的效率以及程序的可读性。由于Visual C# 2005 编译器对输入的代码有自动对齐、退格的功能,所以对于空格的使用实际上已经没有讨论的必要,下面看看空行和括号的使用。

(1)空行

在成熟的源代码中,存在着很多的空行,这些空行很好地显示了代码块的结构。一般来说,在下列元素之间,应当插入空行:

a、构造函数。

b、属性。

c、方法。

d、方法内的逻辑块。

下面看一个关于空行使用的示例(代码中包含了方法内的几个逻辑块):

//************************************************************************************* int x;

int y;

int result;

x = 2;

y = 3;

result = x + y;

Console.WriteLine(result);

//************************************************************************************* 上面的代码中,使用了两个空行把代码分成3个部分(即3个逻辑块),这样的代码看起来简单明了,结构清晰。第1部分:声明变量;第2部分:给变量赋值;第3部分:计算并输出结果。

当然,在如此简单的代码中不使用空行是完全可以的,然而在大型的程序中合理地使用空行是必不可少的。

(2)括号

当代码或者表达式很长时,聪明的程序员会在编写的代码中人为地加入一些小括号,如下面的代码:

//************************************************************************************* int year;

bool boolYear;

bool boolYear = (year % 4 ==0 && year % 100 != 0) || (year % 400 == 0);

//************************************************************************************* 参照C# 运算符的优先级可知,表示闰年的表达式:

(year % 4 ==0 && year % 100 != 0) || (year % 400 == 0)

不加括号完全可以正确计算,然而去掉括号后该表达式看起来结构不如现在清晰。因此,在比较长的表达式中人为地加入一些必要的括号可增强程序的可读性。

1.5.3命名规则

编写代码时,使用良好的风格对标识符命名是一个优秀的程序员必须养成的习惯。变量、函数、结构、枚举、类、属性、事件、方法等的命名都遵循这些规则,这样可以大大地提高程序的可读性,并可方便开发团队中各人员之间的合作。

1. 标识符的书写风格

标识符的书写通常有以下几种风格:

(1)Pascal风格。

大写每一个单词的第一个字符,如WindowsApplication1、MaxNum。

(2)Camel风格。

除了第一个单词,大写其他单词的第一个字符,如maxNum、userName。

(3)全部大写。

如果标识符包含的字符数较少,可以采用全部大写的方法,一般用于常量的命名,如PI、MAX、MIN。

2. 类、结构、枚举和命名空间的命名

类(class)、结构(struct)、枚举(enum)和命名空间(namespace)的命名一般采用Pascal风格,由名词或名词短语构成,且不要使用任何前缀。

例如:Form1、StudentInformation、WeekDays、TxtWelcome等。

3. 参数、变量的命名

参数、变量的命名采用Camel风格,使用描述性的名字,使它能够充分地表示出参数或变量的含义。

例如:maxNumber、userName等。

如果变量仅用来在循环中计数,即作为循环变量,则优先使用i、j、k、l、m、n等。

4. 方法的命名

方法的命名采用Pascal风格,使用动词或动词短语命名。例如:Click、DoubleClick、FormClosing等。

5. 属性的命名

属性的命名采用Pascal风格,使用名词或名词短语命名。例如:BackColor、ReadOnly、ControlBox等。

6. 控件的命名

控件的命名采用Camel风格(Form除外),即首字母小写,而每个后面连接的单词的首字母都大写,命名的形式为:控件名的简写+英文描述(英文描述首字母大写)。

例如:btnOk、lblShow、txtInputNum等。

Visual C# 2008常用控件的简写及应用举例如表1-1所示。

表1-1 常用控件的简写及应用举例

相关文档