笔记参考:广州大学软件工程教学
软件工程是软件工程专业的一门重要学科,掌握好软件工程原理是开发软件的重要基础知识。本博客对软件工程导论进行了详细的讲解,以方便理解。
软件设计:针对需求工程给出的软件需求模型,综合考虑各种制约因素,探求切实可行的软件解决方案并最终给出方案的逻辑表示,这种表示又被称为设计模型
软件设计的制约因素主要来自于资源和技术两方面。
资源制约:在软件开发过程中可以获取的时间,人力,财力,开发辅助工具等
技术制约:待开发目标软件系统可以使用的技术平台
软件设计是需求模型和实现代码之间的“桥梁”,是达成软件质量目标的关键性阶段。
设计元素:出现在设计模型中的模块,这些模块的表现形式包括子系统,构建和类
设计模型是软件问题解决方案的逻辑表示
设计模型的内容应该包括:
综上,典型的软件设计模型一般包含体系结构模型,用户界面模型,用例设计模型,数据模型,子系统/构件/类设计模型
就像我们搭房子要先搭框架,然后再细化房子里面的内容。
软件设计的目标是构建高质量的设计模型。
设计模型的质量要素:正确性(一致性和可行性)、充分性、优化性和简单性
软件设计原则包含:
抽象与逐步求精、强内聚及松耦合、信息隐藏及关注点分离
抽象:集中在某一层次上考虑问题,暂时忽略那些低层次的细节
抽象是管理、控制问题复杂性的基本策略。
软件设计的抽象原则是指:软件设计一般要自顶向下经历一系列抽象级别从高到低的设计阶段,后续阶段会在前一阶段的基础上引入更接近于软件实现的设计元素,这一过程称为“逐步求精”。
将软件系统划分为若干相对独立的部件(模块),所有模块组装后可获得满足问题需要的软件解
但是,并不是意味着我们要不断的将软件系统划分模块,因为总耗费并不是随着划分的模块越多而减少的
为了解决模块化分解相关的难题,引入模块内聚度和耦合度两个概念
内聚度:
内聚度表示一个模块内部各成分彼此关联的程度
内聚度的表现形式:
前三种内聚度较低,4、5内聚度居中,后面两种内聚度最高
模块的内聚度越高越好
耦合度
耦合度是指软件结构中多个模块之间的关联程度。耦合的强弱取决于模块间接口的复杂性,通过接口传递的数据量的大小及复杂性等。
在设计软件时应追求尽可能松散耦合的系统结构
模块间的耦合度直接影响软件系统的可理解性、可测试性、可维护性和可靠性
模块间的耦合度从低到高有五种表现形式:
软件设计时应尽量使用非直接耦合和数据耦合,减少控制耦合,限制外部耦合和公共耦合,杜绝内容耦合
强内聚、松耦合原则
是软件设计领域最重要,最经典的原则之一
模块应设计得使其所含信息(过程和数据)对于那些不需要这些信息的模块不可访问,模块之间仅交换那些为完成系统功能必须交换的信息
好处:支持模块的并行开发,减少测试和后期维护工作量
关注点是指问题求解者针对概念、任务或目标的某个部分或侧面的聚焦
抽象与逐步求精,模块化都是关注点分离原则的具体应用:前者分离“结构”和“细节”,后者分离指责型和功能型关注点
其实就是一个分而治之的原则
可以沿 “职责划分”、“结构-细节”及“通用-专用” 三个维度来分离关注点
完整的软件设计过程的活动:
软件设计过程模型的裁剪方法与需求工程过程模型的裁剪方法相似
软件体系结构,也称架构,从高层抽象的角度刻画组成目标软件系统的设计元素(包括子系统,构件及类)以及他们之间的逻辑关系。软件体系结构是构成后续的详细设计和软件实现的主要工作基础。
在一个设计模型中可以存在一系列抽象级别不同的体系结构模型
抽象级别越低,模型中子系统或构件的粒度越小,软件实现的细节越多。
自顶向下,逐步精化是一种广泛采用,行之有效的设计原则。
体系结构设计的任务是,建立满足软件需求的软件体系结构。
体系结构既要明确定义软件各子系统,构件、关系类的职责划分及协作关系,也要描绘他们在物理运行环境下的部署模型。
体系结构还必须针对软件系统全局性、基础性的技术问题给出技术解决方案,这种方案构成目标软件系统的技术基础设施。
体系结构设计是从what(需求)迈向how(设计)的第一步,选项很多,迷茫很多。
软件体系结构包括三大要素:
软件体系结构涉及的约束的一些例子:
软件需求和体系结构设计之间的关系:
体系结构是以软件需求的实现为目标的软件设计为蓝图,软件需求是体系结构设计的基础和驱动因素。
针对大中型软件项目,软件系统的规模和复杂性都会给体系结构设计造成许多困扰,任何从单一视角的软件体系结构视图都难免遗漏和片面。通常认为,一个软件体系结构设计应该包含以下视图:
用于表达体系结构的逻辑视图的UML图形机制主要是包图和构件图,有时还辅以类图
开发视图的表示可能会用到包图
物理视图用到部署图
因为运行视图涉及到并发,同步以及软件运行过程中的瞬时快照,所以他表示为活动图和对象图
数据视图一般表示为类图或者实体-活动图,但是一般用类图就可以表示
包图刻画包之间的构成和依赖关系。其中,包是UML模型的一种组织单元,他可以包含一组具有逻辑关联的UML模型元素(例如用例、类等),模型图(例如用例图、类图、交互图、状态图、活动图等),以及其他的包。
包在模型管理过程中是配置管理的基本单元,同时也为访问控制提供基本手段。
在设计和实现阶段,包图可以用于描述软件系统的高层结构。
(一)包及包间依赖
从四个角度理解包:
UML以包为基准建立了可见性原则:
包中可见性定义为public的元素可以在模型的任何地方被引用
包的可见性定位为private的元素仅在该元素所在的(最内层)包中可见,其他地方不能引用。
即便建模者不显示的定义包,UML缺省地认为所有无明显归属的元素属于一个隐含的,匿名的顶层包,他是“属于”关系树的根节点。
两个包之间的依赖关系是他们各自包含的模型元素之间的依赖关系在较高抽象层次上的汇总。包的依赖关系是内部模型依赖关系的一个体现。
包间依赖仅仅说明分属两个包的某些元素之间存在依赖关系,而非所有元素之间都存在依赖关系。
包的划分必须遵循强内聚,松耦合原则。
(二)包图
包图是类图的变种。
包图仅体现包之间的两种关系:构成和依赖
如果包图的每个包中仅包含类,就称这类包图为类包图。
如果包图的每个包中仅包含用例,就称这类包图为用例包图。
(三)布局规则
构件是可执行软件系统中的某个可分离的物理模块,他具有精确定义的对外接口,并且外界只能通过接口来访问他。构件是可分离的,他通常表现为一个或数个可独立部署的执行码文件。
构件一般具有较好的可复用性。
构件图
构件图描述软件系统中的构件以及构件之间的构成关系和依赖关系。
(一)构件及其表示
(三)构件定义图
部署图表示软件系统的执行工件在运行环境中的分布情况。
两种部署图:逻辑层面的描述性部署图,物理层面的实例性部署图
描述性部署图描述软件的逻辑布局
实例性部署图在描述性部署图的基础上针对具体的运行环境和特定的系统配置描述软件系统的物理部署情况。
描述性部署图的四类节点:
描述性部署图有四种边:
实例性部署图和描述性部署图之间的关系可类比成对象图和类图之间的关系
对象图是软件系统中某些对象在运行过程中的瞬时快照。
节点表示对象,边表示对象之间的链接
可以将对象图理解为类图在软件系统运行过程中某个时刻点上或某一时间段内的实例化样本。
体系结构的主要任务是建立满足软件需求的软件高层结构,在这种结构中设置软件系统中的所有重要模块并明确定义这些部件的职责划分和协作关系。
体系结构雏形是指软件体系结构逻辑视图的初始形态。
设计模式是指以设计复用为目的,采用一种良好定义的、正规的、一致的方式记录的软件设计经验。
每条模式关注在一般或特定设计环境中可能重复出现的设计问题,并给出经过充分实践考验的软件解决方案。
一种设计模式包含以下内容:
体系结构模式是专门针对体系结构设计问题的设计模式,是软件体系结构设计的经验结晶。
分层模式:
该模式将软件系统按照抽象级别逐次递增或递减顺序划分为若干层,每层由一些抽象级别相同的组件组成。
一般而言,顶层直接面向用户提供软件系统的交互界面,底层则直接负责提供基础性、公共性的技术服务,他比较接近于硬件计算环境,操作系统或数据库管理系统,中间层的抽象级别介于两者之间
层次间的连接有两种形态:
每个层次对上层服务接口的两种组织方式
前一种方式对上层服务请求者更直接,服务提供者所在层次的透明度也高
后一种方式降低了两个层次之间的耦合度。
管道与过滤器模式
管道与过滤器模式将软件系统的功能实现为一系列处理步骤,每个步骤封装在一个过滤器构件中。
该模式仅适用采用批量处理方式的软件系统,不适合交互式,事件驱动式系统
黑板模式
黑板模式将软件系统划分为黑板、知识源和控制器
黑板模式适用于没有确定的求解方法的复杂问题。
概念设计的主要目标是根据关键需求确定初始的软件体系结构雏形。
关键需求包括关键的功能需求项和关键的非功能需求项
辨识关键功能需求项的主要方法
体系结构初创的任务是建立初始的软件体系结构雏形,他属于软件体系结构的逻辑视图,与具体的软件实现技术无关。
建立体系结构雏形的依据主要是前述的关键需求集,注意,建立雏形还需要考虑运行环境。
体系结构的精化目标是将概念体系结构精化成全面的、设计适度的软件体系结构
软件体系结构一般包含逻辑、运行、数据、物理开发五种视图
重点是逻辑视图的精化
概念体系结构与精化后的逻辑体系结构的区别:
设计过程:
与概念体系结构一样,仍采用扩充的UML包图表示精化后的逻辑体系结构
在之前的基础上,添加以下扩充:
允许在包图中出现构件、类和接口,允许在包图中表示子系统和构件的服务接口,采用构造型:
<< sub system > >
<< external sub system> >
<< external component > >
设计技术支撑设施
技术支撑设施应该为多个用例的软件实现提供技术服务,所以,他应该成为整个目标软件系统中全局性的公共技术平台。
当用户需求发生变化时,技术支撑设施应该具有良好的稳定性。
如果目标软件系统的顶层结构采用分层方式,那么技术支撑设施应该位于较低层次。
数据持久存储服务
在目标软件系统结束一次运行之后,其产生的部分数据能够存留于系统的存储介质中,以供本软件下次运行时使用,或者其他软件系统使用。数据存取一般通过数据管理系统实现
确立设计元素
设计元素包括子系统、构件、设计类三种
确定设计元素的接口和相互协作关系,不需要给出设计元素的内部结构和实现途径,此项工作留给子系统设计,构件设计和类设计再进行。
开发视图体系结构主要关注软件源代码文件(含配置文件)的程序分包及目录结构,编译后生成的目标文件包,他们之间的关系以及他们与逻辑视图中各模块之间的映射关系。
开发视图体系结构应该细化至可以支持详细设计和软件实现的并行开展
软件体系结构的物理视图负责展示软件中子系统、构件部署到哪些计算结点上运行,以及这些结点之间的网络连接方式。反映了软件系统的网络运行环境和物理分布状况。
运行视图体系结构主要关注目标软件的并行执行。如果不准备在目标软件中引入并行处理,就不必考虑运行视图体系结构的设计。
主要关注持久数据在宏观层面上存储组织方式,必要时还需考虑数据的传递,备份,恢复和同步方案。
多次不同的软件开发过程中重复使用相同或相似软件元素的过程。软件元素包括源程序模块,目标代码模块,各类文档,测试用例甚至领域知识等。通常将这些可复用的软件元素称为软部件,为了便于复用,通常将可复用的软部件组成为软部件库。目前常见的软部件为类和构件,他们对应的软部件库也就相应的称为类库和构件库。
横向复用是指复用面向不同应用领域中软部件,例如数据结构,分类算法,人机界面控件等。标准函数库即是一种典型的,原始横向复用机制。
纵向复用是指一类具有较多公共性的应用领域之间进行软部件复用。纵向复用的关键点在于领域分析:根据应用领域的特征及相似预测软部件的可复用性。
针对采用面向对象方法开发和基于类库的软件复用方法的软件项目,可以采用继承或代理方法来复用类库中的类。
在横向复用的情况下,必须确保构件具有跨越多个差异较大的应用领域的可复用价值。
在纵向复用情况下,必须根据领域分析的成果创立构件。
由于纵向复用的潜力远大于横向复用,所以他是构建创立过程中的首要活动。
领域分析
从软件工程的观点看,领域就是向目标软件系统提出应用需求的问题及背景知识。
领域分析的主要任务是,针对单一或一族相似的领域,以软件复用为目标,探寻并挖掘领域或领域族中能够为多个目标软件系统共用的软构件。
检查前面获得的软件体系结构是否足以支撑所有软件需求项的实现,是否还有进一步优化的空间
以用户为中心的设计
屏幕:窗口,对话框,网页
屏幕之间存在页面跳转,称为“界面流”
用户界面设计过程主要活动有:
详细设计是软件设计过程的最后环节。
在将设计模型提交给软件编程人员展开软件实现之前,有必要将用例设计,子系统设计,构件设计,类设计,数据模型设计的成果进行整合和必要的优化, 并再次对其进行验证,研究其是否足以支撑所有软件需求项的实现,是否还有进一步优化的空间,是否存在设计不充分的地方。
用例设计的子活动归纳:
子系统设计的任务是,确定子系统内部的结构,即,设置包含于其中的,粒度更小的子系统,构件和设计类,明确他们之间的协作关系,确保他们能够协同实现体系结构中该子系统的服务提供接口所规定的全部功能和行为。
构件的任务是,为实现构件的服务提供接口中规定的职责而在其内部设置子构件和类,明确他们的职责,定义对外接口,确定他们之间的协作关系。
构件的详细设计必须确保接口与实现相分离。
软件设计师必须分析当前以及将来可能的多种应用场景中对构件的功能需求的相同点和不同点,采取以下方法来提高构件的可复用性:
构件的定制机制是提高构件的灵活性和可复用性的主要手段之一。
构件通常基于执行码进行组装
上述方法有两个明显的缺陷:当构件接口发生变化时,接口描述文件必须相应的改变,因人为错误可能直接导致描述文件与实际构件接口不一致。
自描述接口可以解决上面的问题。其基本思想是,支持构件组装的软件开发环境或构件的运行平台自动从构件的执行码中综合出构件的接口定义,在自描述接口机制的支持下,构件组装有两种途径:静态组装和动态组装。
对体系结构中出现的关键设计类,以及界面设计模型,子系统设计模型和构件设计模型中出现的类进行细化设计,以使他们足够精细,能够直接提交给软件构造阶段进行编码实现。
为了使类图精细化至足够的程度以供软件实现工程师展开编程实现,软件设计师必须详细研究所有的设计类的属性和操作,并完成以下任务:
数据模型设计的任务是,确定设计模型中需要持久保存的数据条目,基于数据模型设计这些数据条目的组织方式,必要时还需设计特定于本软件项目采用的数据库管理系统的优化机制,以提高持久数据操作的性能。
设计整合的任务是,汇总迄今获得的所有设计模型,包括体系结构模型,界面设计模型,用例设计模型,子系统/构件/类设计模型,数据模型,在全局范围内检查并消除他们之间的不一致性,剔除冗余性,最终形成设计规约
设计验证的任务是,基于设计规约,重新审视所有软件需求项(包括功能需求项–用例,以及非功能需求项)的实现方案,研究如何化解迄今标识出来的所有重要的全局风险,在此过程中验证详细设计的正确性,优化性和设计充分性
软件实现是指,通过程序设计及编码的过程,把软件详细设计映照为计算机可以“理解”并最终可运行的代码,它涉及编写代码、单元测试、集成测试、调试、确认等多项活动,是一个迭代的过程,他除了要求编写的代码完全符合软件设计确定的功能,还需要控制和降低程序复杂性,增强程序的可维护性
调试的方法:
可以认为,一个基于计算机的信息处理系统由数据流和一系列的转换构成,即IPO模型
软件系统通过一系列的转换(也称“加工”)将输入数据变换为输出数据
数据流图就是用来刻画数据流和转换信息系统建模技术,任何软件系统都可以用数据流图表示。
数据流图用简单的图形记号分别表示数据源,数据流,转换以及外部实体。
数据存储的流入与流出:
加工:
使用控制流建模:
数据字典的其他含义:
数据字典的每一条目的内容:
数据库数据字典: