第一周 概论
- 软件是什么?
计算机系统中的程序及其文档, - 软件有什么特点?
软件是无形的,由设计开发而来,较为复杂,开发成本高,易于复制,开发只是部分成本。 - 软件的分类?
系统软件、支撑软件、应用软件。 - 软件发展的三个阶段?
个人编程-》小作坊生产-》软件工程 ,产生了质量差、投入高、开发复杂性和成本越来越高的问题。产生软件危机。 - 软件工程定义
将系统的、规范的、可量化的工程化方法引入到软件的开发、运行和维护过程中。
就是用工程化的方法来开发和维护软件,解决软件危机。 - 软件开发的本质
本质是:从问题域上的概念和处理逻辑到运行平台上的概念和处理逻辑的映射。
这个映射过程太过复杂,对这个过程根据抽象程度的不同进行分层,从问题域=》需求层=》设计层=》实现层=》解空间。
建模是实现映射的一般途径。 - 什么是建模?
利用背景知识,通过抽象,对半结构化和非结构化的问题进行一个机构化的描述。
在特定的角度和抽象层次,对问题进行去粗取精,给出边界,模型元素以及彼此关系的描述。
第二周 软件需求
-
软件需求的作用?
软件需求是系统需求规约中分配给软件的那部分需求,它规定了需求和约束,并作为软件设计和开发的基础以及测试验收的依据。 -
需求的定义
一条需求是一段需要构造的陈述,描述了产品/系统在功能上的能力,性能参数以及其它性质。
需求不是一句话,它需要满足必要的、无歧义的、可测的、可追踪的、可测量的五个要求。 -
需求的分类
功能:描述了能力,不仅要说清楚能做到什么,也需要说清楚该功能的前置条件,对异常条件的映射,内部产生的错误处理,与其它功能的互斥条件,系统内部转换的状态,必要的公式等。
性能:性能需求和功能需求不是一一对应的,通常是一对多。描述了一个系统或者构建所需要达到的性能指标。
外部接口:描述了一个系统和外部交互的软硬件,通常分为硬件、软件、用户、系统、通讯接口等。
设计约束:从成本或开发角度来看对整个系统的约束。
质量属性:描述了软件必须要达到的性能或质量指标,包括可靠性、存活性、安全性、友好性、可移植性。等质量指标。 -
需求的提取
自悟:把自己当做系统的最终用户,来提取可能的需求。
交谈:直接向用咨询需求,但要控制住边界。
观察:直接去现场观察用户现有操作逻辑,再从中抽取出需求。
小组会:由项目经理或者软件工程师把控会议进程,和客户一起探讨需求。
提炼:从现有的技术文档中提取软件需求。 -
软件需求规约
软件需求规约是以上方式提取需求的正式文档,是系统的概念模型。软件需求规约需要满足以下特点,
(1)重要性和稳定性程度,要有侧重,哪些是必须,哪些是可选。
(2)可修改性,单个需求得是可修改的,并且不能影响其他需求。
(3)完整性,不能遗漏提取的需求。
(4)一致性,规约中的需求不能互斥。 -
软件需求规约的作用
(1)软件开发人员和需求方事实上的技术合同书。
(2)对于项目的管理工作,软件需求规约是一个管理控制点,以此作为依据进行管理。
(3)对于软件设计人员而言,需求规约是一个起始点。
(4)需求规约是创建软件测试文档和用户指南的基础。 -
项目需求
软件需求关注的是产品,描述的是交付给客户的产品是什么。
项目需求指的是为了交付客户产品,整个项目组的开发者要做什么,也称之为项目的范围。
第三周 结构化分析
-
结构化分析方法的概念
软件开发方法:软件开发过程中所遵循的办法和步骤。如结构化、面向对象、面向数据、敏捷等方法。
结构化方法包括:结构化分析、结构化设计、结构化的程序设计。 -
需求分析的目标
对需求进行,解决其中的歧义和不一致的问题,以系统化的形式给出用户的描述,给出问题形式化或半形式化的描述。
为了实现这个目标,需要提供一组用户听得懂的术语,用这些术语描述问题模型,给出指导过程。 -
结构化分析的术语
在结构化的模型中主要涉及以下五个术语:
数据流:数据的流向
加工:对数据进行变换的操作,是系统功能的抽象。
数据存储:数据的静态结构
数据源:系统之外的实体,是数据流的起点。
数据潭:系统之外的实体,是数据流的终点。
数据流和数据存储支持的是数据的抽象。加工是代表我们想对数据处理的内涵。数据源和数据潭支持的是系统边界的抽象, -
模型化表达工具
(1)数据流图
是描述系统数据变换的图形工具。数据源、数据流、加工、数据潭、数据存储。
(2)数据字典–》数据源数据流
数据字典定义了数据流和数据存储的结构,并给出各项数据项的基本数据类型。
数据字典就是结构+数据项说明。使用以下逻辑操作符来表示结构。
(3)判定表或判定树
就是对加工的详细说明,判定条件。描述加工的输入数据和输出数据的逻辑关系。 -
结构化分析过程
(1)建立系统功能模型
先建立顶层数据流图,确定系统边界,再自顶向下逐步求精建立系统的层次数据流图。
首先从需求陈述中提取要点,绘制顶层数据流图。
顶层的数据流图主要展示系统边界以及数据流向,将主要的加工抽象成一个系统。
有必要对复杂的加工进行分解,细化内部细节。
顶层-》0层-》1层-》2层-》3层
如何进行拆分呢? 需要选择一个角度,比如使用系统的人和对应的功能进行拆分。
针对0层拆分出来的加工,要明确顶层的数据流在0层的加工中如何展示。同样多个加工之间也是有数据交互的,而通常是通过数据库或者数据文件来进行多个模块之间的关联。
如果要进一步细分,则从0层选择一个加个进行分解,得到1层的数据流图。
需要注意的是从1层开始就得进行层级编号,表明对于的上层哪个加工模块。
(2)建立数据字典
根据数据流图,建立数据存储、数据流、定义数据项。
(3)给出加工小说明
使用语言描述、判定表、判定树集中描述一个加工在做什么,执行的条件优先级和执行频率等。
-
需求规约说明书
(1)引言
(2)概述
(3)数据流图、数据字典、加工说明
(4)接口
(5)性能需求
(6)其他说明
结构可以参考往上的模板。 -
需求规约注意点
(1)正确性:
(2)无二义性:
(3)完整性:
(4)可验证性:
(5)一致性:
(6)可理解性:
(7)可修改性:
(8)可追踪性:
(9)设计无关性:
(10)注释:
第四周 结构化设计
-
什么是结构化设计
是一种软件开发活动,定义实现需求规约所需的软件结构。
目的是根据软件需求规约,在一个抽象层次上建立系统软件模型。定义软件体系结构、处理算法最终产生设计规格说明书。 -
结构化设计的内容
结构化设计分位总体设计和详细设计两部分。
总体设计:
体系结构设计:从分析模型导出,定义了软件模块及其之间的关系。
接口设计:从顶层数据流图的出外部接口设计,包括用户界面,目标系统及其其他的软硬件系统。内部接口设计是系统内部各模块的接口。
数据设计:根据数据字典,设计软件系统所需的文件系统,以及数据库表的设计,
详细设计:模块内部设计(包括算法和数据结构)。 -
总体设计
模块:用方块表示,是一种可以独立标识的软件成份。
调用:用横线表示,模块间的依赖关系。
模块结构图MSD:表示软件系统的静态结构。应用上面两个术语和符号来对模型进行建模。
总体设计的目标是:将数据流图DFD转化成模块结构图MSD。 -
数据流图的分类
(1)变换型数据流图
数据流图有输入部分,从物理输入转化成计算机可识别的部分;输出部分:将计算机计算结果转化成外界系统可接受的格式那部分;在输入和输出中间的那部分称之为变换部分。而输入部分的输出结果就是变换部分的逻辑输入,变换部分的逻辑输出就是输出部分的逻辑输入。
(2)事务型数据流图
事务型数据流图的特点就是有一个输入经过加工分成多个输出。接收一个输入,分析并确定该事务要执行的路径。 -
变换型数据流图设计准则
(1)复审并精化系统模型
(2)确定输入、变换、输出这三部分的边界
(3)进行顶层级分解
(4)第二级分解-自顶向下逐层分解
就是对顶层输入输出模块进行拆分(输入+变换+输出)直到某一模块的逻辑输入变成物理输入为止。最终得到的结果是如下图所示:
上面是需求分析部分;下面是需求设计部分,软件解的部分。其实结构化分析和设计不是一一对应的,所以变换过程会存在一些歧义的问题。 -
事务型数据流图设计准则
(1)复审并精化系统模型
(2)确定事务中心
(3)第一级分解-系统模块结构图顶层和第一层的设计。
首先以事务为中心设计一个主模块;
然后为每一条活动路径设计一个事务处理模块;
对输入部分设计一个输入模块;
如果不是所有输出都汇集到一个模块,则第一层无需设计输出模块。
(4)第二层分解,自顶向下逐级分解
7. 总体设计的精化
对以上形成的模块设计图,按高内聚低耦合的原则进行调整,最终形成可供详细设计的模块设计图。
模块:执行一个特殊任务的一组历程和数据结构。
接口:给出可由其他模块访问的对象。
耦合:是不同模块之间依赖程度的度量。
产生耦合的原因,一个模块对另一个模块的引用,一个模块向另一个模块传递数据,一个模块对另一个模块施加控制。模块调用过程中数据结构的复杂程度都会影响到耦合强度。
耦合的种类(由强到弱):
(1)内容耦合:一个模块修改或操作另一个模块的数据。
(2)公共耦合:两个以上的模块共同引用同一个全局数据项。
(3)控制耦合:一个模块向另一个模块传递一个信号,接受该信号的模块将依据该信号执行必要的步骤。
(4)标记耦合:两个模块至少有一个通过界面传递的参数。传递比较复杂的数据结构。
(5)数据耦合:模块间通过参数传递基本类型的数据。
所以如果两个模块之间必须产生耦合,那么尽量使用数据耦合,少用控制耦合,限制功能耦合涉及的模块,避免使用内容耦合。
内聚:是一个模块内部各成分之间相互依赖程度的度量。
内聚类型(由低到高):
(1)偶然内聚:一个模块之内各成分之间没有关系。
(2)逻辑内聚:几个逻辑上相关的功能放在同一个模块。
(3)时间内聚:一个模块完成的功能必须在同一时间内完成,而这些功能只是由于时间上的关系关联在一起。
(4)过程内聚:各成分的处理必须按一定次序执行。
(5)通信内聚:各成分操作的数据在同一模块内。
(6)顺序内聚:各成分与同一功能相关,前一成分的输出是另一成分的输入。
(7)功能内聚:模块的所有成分对完成单一功能都是最基本的,必须的。
-
总体设计案例
总体设计首先要对数据流图进行输入部分、转换部分、输出部分的划分。
输入部分从物理输入开始,到完成数据采集转化成业务可用的基础数据为止。
输出部分从物理输出开始,到接受到业务数据结果为止。
中间的是转换部分。
划分好之后就可以输出顶层模块设计图
之后对各部分进行进一步细化。
对输入部分进行细化时,重点考虑有几个输出,以及每个输出最开始的来源。
-
精化模块结构图的启发式准则
(1)改进软件结构,提高模块独立性。
通过模块的分解与合并,降低耦合提高独立性。多个模块相同的代码可以下沉到一个子模块。
(2)模块规模适中,单一模块要能写在一页纸内。
拆分大模块,频繁调用的小功能提到上层模块。
(3)深度、宽度、扇入、扇出规模要适中。
深度:软件系统中控制的层数,标志一个系统的大小和复杂程度。
宽度:软件系统中一个层次中模块总数的最大值。
扇入:表示有多少个上级模块调用当前模块,在不违背模块独立性的前提下,扇入越大越好。
扇出:一个模块直接控制的下级模块数,
扇出过大表示当前模块功能太复杂,依赖太多下层模块,需要增加中间模块来降低复杂性。
扇出过小表示当前模块功能过度集中,当前模块和依赖的功能过度重合。
好的系统应该顶层扇出高,中层扇出少,底层扇入高,整体呈葫芦形。
(4)模块的作用域力争在控制域之内。
作用域:首该模块内一个判定影响的所有模块的集合。
控制域:模块本身以及直接或间接依赖的所有模块。
正常情况下只要不相互依赖就好。
(5)降低模块接口的复杂性
不要传递多余的参数,只传递必须的参数。
(6)模块功能应该是可以预测的,相同的模块应该有相同的输出
即模块最好不要有状态, -
详细设计
每个模块内部的算法和数据存储的设计。
结构化的程序设计,一个程序的设计仅通过顺序、选择、循环这三种结构进行连接,且每个代码块都只有一个入口和出口。
程序内部逻辑,详细设计的工具有:
(1)伪码
(2)程序流程图,不适合表示全局结构
(3)PAD图
(4)N-S图 -
软件设计规约
对软件的组织及其组成成分的内部结构的描述。
(1)概要设计规约
表明软件的组织结构,包括系统环境、设计描述、对每个模块的描述、文件结构和全局数据。以及软件测试方面的要求和说明!
(2)详细设计规约
是对软件各组成部分的细化,增加了处理过程的算法以及数据结构。
软件设计规约的格式请参考网上标准。
- 结构化方法小结
结构化方法的世界观
一个系统是由信息流组成的,每条信息流都有自己的起点和重点以及驱动信息流的加工。所以信息处理表现为信息的流动。
如何基于结构化方法的世界观来分析问题?
自顶向下逐级分解,数据抽象(数据流和数据存储的抽象)、功能/过程抽象(数据加工抽象)、模块化(结构化设计,拆分模块降低系统复杂度,模块复用,高内聚低耦合)。
结构化方法的弱点:
结构化方法以捕获问题域中的“过程”和“数据”来进行解空间建模,而过程和数据往往是事物易变的性质,导致后期系统维护困难,数据结构或者模块的变动会导致整个系统不可靠。
- 软件设计评审
第五周 UML模型
-
面向对象方法的世界观
一切系统都是由对象构成的,对象之间相互作用与影响构成了复杂系统的功能。
面向对象方法就是以对象以及对象的关系来构造软件系统的方法。
有意思的是在80年代现有面向对象语言的诞生,后有面向对象方法的成熟。
面向对象方法强调直接以问题域中的事物来思考和分析问题,根据事物的特征来抽象成系统中的对象,再运用人类日常生活中的思维来简化模型。 -
面向对象是什么?
(1)面向对象是一种软件系统方法学,包含了如何看待软件系统与现实世界的关系,以什么样的观点来求解问题,以及如何进行系统构造。(2)对象是系统中用来描述问题域中一个事物的客观实体,是构成系统的一个基本单位,由一组属性(对事物静态特征的描述)以及对这组属性进行操作的方法(对事物动态特征的描述)构成。
(3)将一个事物的属性和方法封装(只暴露外部所必须的内容,屏蔽内部实现细节,降低模型复杂度)在一起就构成了对这个事物的(建模)。
(4)再将问题域中提取出来的对象根据相同的属性和方法进行分类,这些相同的属性和方法就是对这一类对象的抽象描述,而具体的每个对象就是该类的一个具体实例。
(5)属性和方法完全一样的对象归为一类,系统中得到的类会很多,并且有很多部分相同的情况。此时再根据类与类之间的相似程度,进行不同程度的抽象归类,提取出共有部分就会得到这些类型的父类,子类继承父类并实现个性化的部分。
(6)当有些对象的属性和方法特别多时,为了简化模型,可以将复杂对象拆分成多个简单对象。根据简单对象的重要性又可以细分一下。
todo 这部分需要确定下
~~如果简单对象是复杂对象不可或缺的一部分,创建一个复杂对象就必须先创建好简单对象,那么这个简单对象和复杂对象的关系是聚合(部分和整体是紧密的关系)。所以聚合的简单对象一般要么在复杂对象里边创建,要么就是复杂对象构造函数必须的参数。如果简单对象是复杂对象非必须一部分,缺少简单对象不影响复杂对象的创建,则找个简单对象和复杂对象的关系是组合,组合的对象可以由外部注入~~ 。
(7)关联
-
UML是什么?
UML是可视化的统一建模语言,可用于软件系统的分析和设计。
在需求获取层,可以使用用例图。
在需求分析层,可使用类图,交互图。
在设计层,可使用类图,交互图。
包是面向对象中,用于控制组织复杂性的机制。 -
类和对象
类是一组具有相同属性、操作、关系和语义的对象描述。对象是类的一个实例。
类 = 类名+属性+方法。
(1)类名
一般黑体居中,首字母大写,当为抽象类时是斜体字。
(2)属性
用于表示对象状态的数据,类属性(静态属性,共享),实例属性(非静态属性,实例私有)。
描述属性格式为[可见性] 属性名 [:类型] [多重性] [= 初始值] [{特性串}]
可见性:共有(+ 或 public)、受保护的(# 或 protected)、私有的(- 或 private)、包内的(~ 或 package )
属性名:这是必须的,小写字母开头,左对齐。
类型:是对属性类型的约束,和具体语言有关。如:name:String
多重性:表示值的范围,name[0…1]:String,[0…1]代表可以为空,默认是[1…1] 代表不为空。
初始值:name:String = “tom”
性质串:
(3)方法
小驼峰命名,
描述格式[可见性] 操作 [(参数列表)] [:返回类型] [{性质串}]
可见性:参考属性
操作名:小写字母左对齐,
参数表:[方向] 参数名: 类型 [=默认值]
参数方向:in (输入参数,不可修改) inout (输入参数可能要对其进行修改) out () -
接口
接口体现的是功能的抽象,是一组操作的集合,起的接缝的作用。
使用<<interface>> 接口名
来展示接口名称。
虚线空心三角代表商品实现了销售接口。 -
协作
协作是一组类,接口和其它元素的群体,用虚线椭圆表示。 -
用况
体现功能的需求,是一组动作序列的描述,系统执行特定描述产生对特定参与者一个有价值的结果。
描述了系统一个完整的功能,用实线椭圆表示。 -
主动类
体现并发行为的抽象,是一种至少有一个进程或线程的类。 -
构件
是系统中逻辑的可替换的成分,遵循并提供了一组接口的实现。
-
制品
是系统中物理的可替换的部件,
-
节点
-
包-用于控制复杂性的概念
包是UML中划分类目分组的机制,分组中可以是字包,也可以使其他类目的元素。
包之间的依赖关系分为,
引入依赖:<<import>>
就是可以传递的引用,B引入C,C的公共部分相当于成为B的一部分,A引用B包则可以间接使用C包中的内容。
访问依赖:<<access>>
就是不可以传递的引用,B访问依赖C,B可以访问C中的公共部分,但C的公共部分不是B中的公共部分,所以A引用B的时候,不可以访问C中的内容。 -
关联
关联(association)是类目之间的结构关系,描述了一组具有相同结构和相同语义的链。链是对象之间的连接。
关联强调的是静态的结构上的关系, 而不是调用上的关系。
关联可以用一条线来表示。
关联名:关联的标识,用于标识该关联的含义。可给出关联方向。
角色名:一个类参与一个关联的角色标识。在类的一个关联中,可以显示的命名该角色。
多重性:多重性表示的是,多对多的关系。
一个人可以拥有1-2台设备,而一个设备只能被0-1个人拥有。
关联就是一条线,线的两端连接的实体可能会有不同的数量对应关系。
1…*代表 一个公司可以有1到多个人。
* 代表的每个人可以被0到1个公司雇佣。
了解了关联的表示,那么就可以看看常见的关联关系。
常见的关联关系有聚合和组合。
聚合: aggregation 一种特殊形式的关联,表达了一种整体和部分的关系。即一个一个类表示一个大的事物,它由一些小的事物(部分)组成。
聚合用菱形箭头表示,标记在靠近整体的那部分。
比如:一个班级由40个人组成,这40个人毕业了,这个班级就不存在了,但是这40个人还是存在的,这就是聚合。
整体和部分的生命周期是不一致的,整体不存在了,部分还是可以存在的,就是聚合关系。
不管是整体类还是部分类,他在概念上是属于同一个层次的。在建模实践中,这是区分是否把一类事物标识为一个部分类,还是把他标识为一个类的属性的基本准则。
组合:如果整体类的实例和部分类的实例具有相同的生命周期,这样的聚合称之为组合。
组合是聚合的一种形式,整体和部分之间具有很强的属于关系,具有一致的生命周期。
组合的末端,就是整体的那边,显然多重性不能大于1,因为一个部分只能属于一个整体。
如果部分类和整体类的生命周期一致,那么可以把部分类当做整体类的属性。
-
泛化
泛化指的是一般性事物和他较为特殊的子类之间的关系。就是父类和子类的关系。
子类可以继承父类的属性和操作,并可以有更多的属性和操作。
子类可以替换父类的声明。
如果子类的一个方法实现覆盖了父类的实现,这种情况称为多态性。
泛化就是继承关系,用实线+三角箭头表示,箭头指向父类。
-
细化(实现)
细化是类目之间的一种语义关系,一个类目约定了规范,另一个类目来执行。
使用虚线+空心三角箭头 表示,箭头指向规范的类目,
商品实现了销售这个接口所要求的规范。
下订单实现了管理订单这个用况所要求的功能需求。 -
依赖
依赖是一种使用关系,用来描述一个事物使用另一个事物的信息和服务。
依赖是使用关系,最简单的就是一个方法中的参数是另一个类型,这就是使用关系上的依赖。
上面讲了类与类中的4种关系,关联、泛化、实现、依赖。类图表示的是一种静态的结构关系,尽可能使用关联、泛化、实现,来绘制类图。依赖是一种动态使用关系,使用关系一般是在交互图中进行展示。
如果是一个类对另一个类属性或信息上的依赖,可以在类图中使用依赖。
第六周 UML工具
静态部分建模工具:
(1)类图:表示类,类的内部结构以及类与其他类之间的关系的图。
(2)构件图:表达系统有哪些构件,以及构件之间的依赖关系。
(3)组合结构图:类与协作之间的关系,可以看做一部分的类图。
(4)对象图:表达了一组对象,以及他们之间的关系。
(5)制品图:一组制品及其之间的关系。
(6)部署图:表达运行时系统中的不同结点,以及结点上生存的制品的配置。
动态部分建模工具:
(1)用况图:需求用况
(2)状态图:当对象的状态比较复杂时,可以用状态图来作为辅助模型描述对象状态变化。
(3)活动图:对象活动的控制流图。
(4)顺序图:描述紧密相关的一组对象的交互关系。
(5)通信图:注重有交互关系的对象描述
(7)交互概观图:
(8)定时图:
-
类图
绘制类图流程:
(1)对系统中的概念进行建模,形成类图的基本元素(类,接口),以及各部分的责任。
(2)对各元素之间的关系进行建模。关联、泛化、依赖。
(3)对系统之间的协作进行建模,协作就是多个类为了完成同一个任务,彼此之间的协同工作。 -
用况图
用况图是对系统行为的描述,
用况图中包含的元素主要有:
参与者(Actor):是一组高内聚的角色,
用况:用况表示参与者使用系统的一种方式,也是系统可以执行的一个操作序列。
主题:是由一组用况描述的子系统。
关联:参与关系,是操作者和用况唯一的一种关系。
扩展:用况之间的一种关系,用况A扩展了用况B。
包含:用况A包含用况B,是A包含B的一部分
泛化:A到B的泛化指的是A是B的特殊情况。
用况图的使用场景
(1)对系统语境进行建模,首先要识别参与者,进行归类。
(2)分析参与者所需要的系统行为作为用况。
(3)对收集的用况进行整理,处理重复冗余形成泛化关系。
(4)模型化用况图中的各类关系,建立关联。
(5)最后通过注解和约束给出用况的非功能性需求。
-
顺序图
顺序图描述的是一组对象以及这些对象之间的交互关系。
顺序图主要包含以下元素:
交互各方:角色或对象,有生命线。
交互方式:同步或异步,同步是三角箭头,异步是枝型箭头。
交互内容:消息
控制操作符:表明消息调用的特征,比如循环调用(loop),并发调用(par),选择调用(alt),表明了在满足什么条件下消息的调用。
外加额外的注释构成了交互图。
-
状态图
也叫做状态机图,强调了从一个状态到另一个状态的控制流。
状态机图的元素:
(1)状态
一个对象在其生存期的一种状态或情况,
状态分为:
初态:实心球,开始状态。
终态:圆圈加实心球,终止状态。
正常状态:包含业务含义的状态。
活动activity:活动是状态机中一种可中断的状态,中断后仍可继续。
动作action:动作是状态机中不可中断的一种原子操作,他可导致状态的改变,或者一个值的返回。
entry 和 exit是两个特殊的动作标号。entry表示进入该状态所需要的执行的操作,exit表示退出该状态时所需要执行的操作。一个活动通常由多个动作组成。
子状态:子状态是包含在其他状态中的状态,相当于一个状态中包含了一个状态机。不包含子状态的状态称为简单状态,包含子状态的状态称为组合状态。子状态机也分为顺序子状态机(非正交),并发子状态机(正交)。
上图就是一个正交的子状态,从外部状态进入到子状态,由于是并发的,这里进入的时候要分叉,等两个子状态机跑完后,要进行合并重新汇合成一个动作。
被延迟事件:一个状态中不予被处理的事件列表。
(2)事件
一个事件是对一个有意义的发生的规约。内部事件(系统对象之间传递的事件)外部事件(系统和他的参与者之间传递的事件)
事件的模型:
信号singal:信号是消息的一个类目,有属性和操作,信号之间可以有泛化。信号是一种异步事件。
调用call:一个调用事件表示对象接收到一个操作调用的请求。
时间事件:表示推移一段时间的事件。
变化事件:表示一个条件得到满足或者状态的一个变化。
发送事件和接收事件:
(3)状态转移
状态转移是两个状态之间的一种转换关系。
状态图的一般用法:
(1)选择状态图应用的场景,类、用况、子系统。
(2)选择实例,并给出初始状态和最终状态,以及对应转换条件。
(3)确定一个时间段,识别实例在这个时间段内的状态变化,以及是否有子状态。
(4)识别状态转换的事件有哪些,为状态转移添加动作。
第七周 面向对象分析
- 面向对象分析概述
面向对象分析(Object-oriented analysis)就是运用面向对象方法,对问题域(被开发系统的应用领域)系统责任(所开发系统应具备的职能)进行分析和理解,找出描述问题域和系统责任所需的类和对象,定义这些类和对象的属性和操作,以及他们之间所形成的各种关系,最终目的是产生一个符合用户需求,并能够直接反映问题域和系统责任的OOA模型及其规约。
2.OOA的过程
(1)定义用况图,对用户需求进行规范化描述。
(2)发现对象,定义内部属性和操作。
(3)明确对象之间的关系。
(4)使用包图来控制类图复杂性。
-
识别类的过程
(1)研究问题域和用户需求
研究用户需求,明确系统责任,阅读原始需求,澄清需求。
研究问题域,听取专家见解,阅读问题域相关资料。
确定人、设备和外部系统与内部系统的边界,明确外部接口。
(2)策略和启发
先识别问题域中的人员、组织、物品、设备、事件、表格、结构等事物,
人员:需要设备保存和管理的人员信息,需要在系统中提供某些服务的人员。
组织:在系统中发挥一定作用的组织结构,院系班级小组等。
物品:需要系统管理的物品,比如货物,商品,书籍。
设备:在系统运行过程中,由系统监控或管理的各类设备。
抽象事物:没有具体的形态,却对用户的业务有实际意义的逻辑上的事物。比如计划,安排,日程规划。
事件:需要由系统长期记忆的事件。
文件:线下传递信息的各类文件,比如表格、档案、证件、票据。
结构:结构是将其他对象联系在一起的一种关系。其次考虑系统边界,与系统直接交互的工作人员以及外部设备等。
(3)审查和筛选
舍弃无用的对象,对系统而言是否是否提供了有用的属性和操作。
对象的精简,将只有一个属性或操作的类合并到其他相关类中。
与实现有关的对象可以延迟到OOD阶段。
(4)识别主动对象,对系统中主动发起事件的参与者。
(5)对象分类,建立类图中的类
使用问题域和系统责任知识,为每组具有相同属性和操作的对象归为一类。
为拥有特殊属性的对象划分特殊类,形成泛化关系。
对相似的类分析公共部分提取出一般类和部分类。
对实际差别很大,但在系统中使用共同关键信息的类也可以考虑合并。
-
识别属性和操作
分析对象属性
(1)识别属性
首先是按常识来判断这个类该有什么属性,
在当前问题域中该有哪些属性
要承担对应系统责任需要哪些属性
这个对保存和管理哪些信息?
对象是否有状态,用什么属性用来表达?
对象为了要实现对应功能,需要什么属性做支撑
针对聚合和关联关系,改用什么属性表示?
(2)审查和筛选
属性是否以系统责任为目标的抽象?
是否破坏了对象特征的原子性?
是否可以通过继承得到?
是否可以通过其他属性直接导出?
针对规范性、性能等与实现条件有关的问题都推迟到OOD考虑。分析对象行为
(1)识别行为
根据当前对象在系统中承担的责任,需要什么操作?
当前对象在问题域中有哪些行为?
对象的状态转换应该有哪些操作?
对象执行业务流程所必须的操作?
(2) 审查和调整
审查对象的每个操作是否提供了系统责任所要求的功能
调整无用的操作
分析是不是高内聚,一个操作是不是单一的完整的功能。
(3)识别对象的主动行为
对象的行为是否是主动触发的?
与系统边界外的活动者直接进行交互的操作?
根据系统责任观察功能构成层次,一层一层分析对象该有什么操作?
(4)对操作进行命名,动词或动宾结构
对操作进行详细说明 -
识别对象之间关系
(1)识别继承(泛化)关系
一种思路是把每个类看做一个对象集合,分析这些集合之间的包含关系。理出一般和特殊关系。
另一种是看一个类是不是具有另一个类的全部特征(属性和操作)
学习当前领域的分类学知识。
按照事物常理来进行分类。
检查多个类中共同的属性和操作,提取公共类。
考虑领域范围内的复用来识别继承关系。
审查和调整继承关系是否合理。是否合理,“is a kind of”分析,、
对继承关系进行简化,如果多个特殊类只是单一特征不同,可以添加属性来体现差异。
取消单一用途的一般类,减少继承层次。
(2)识别关联
首先识别对象之间的静态关联
认知关联的对象之间所需的属性和操作,必要时添加关联类。
分析关联的多重性,一个A类型对象和多个B类型的对象关联,把n标记在B类型那边。
关联的线两端可以给出关联关系中扮演的角色。
(3)识别聚合关系
聚合是整体和部分的关系,
分析角度可以是物理层面,组织构成,团体和成员,抽象事物的整体和部分,具体事物的某个抽象方面。
审查和筛选,得到的关系是否属于问题域中,是不是系统责任所必须,是否明显。
根据聚合关系调整对象层和属性层。
(4)识别依赖
依赖是一种使用关系,一个事物使用另一个事物的信息和服务。
大多数情况是使用依赖描述一个类使用另一个类的操作。(依赖的类型通常作为方法的参数类型)
注意:在初步建立类之间的关系时,可以暂时使用依赖。在最终的类图中,如果能用其他关系明确指出类之间关系的含义,最好就不要使用依赖。
第八周 面向对象设计和编程
-
面向对象设计概述
OOD 是在OOA模型的基础上按实现条件进行必要的修改,调整和细节补充。
OOD中使用的概念和模型与OOA 是一致的,更多的是从实现层面出发来来进行调整。 -
如何进行问题域部分的设计
(1)为复用设计与编程的类而增加结构,就是对相似的类进行增加或减少属性和操作,提高复用性。
(2)增加一般类建立共同协议,就是给多个不同类增加共同的基类。
(3)按编程语言调整继承和多态。采用聚合,将多继承转换为单继承,
继承是is a kind of,聚合是has of
(4)提高性能,考虑数据传输时间、数据存取时间、数据处理时间。合并通信频繁的类。增加属性减少重复计算,用聚合关系描述复杂类。
(5) 为持久化存储需要对设计做的修改。 -
人机交互部分的设计
-
控制驱动部分设计
(1)识别控制流,以结点为单位识别控制流。
(2)从用户需求出发识别控制流。
(3)从usecase中识别控制流。
(4)参照OO模型中的主动对象。
(5)为改善性能而增加的控制流。
(6)实现并行计算的控制流。
(7)实现结点间通信的控制流。
(8)筛选和审查取消不必要的控制流。 -
数据管理部分的设计
(1)对象在数据库中的存放策略,把由每个类直接定义并需要永久存储的全部对象实例存放在一个数据库表中。首先列出每个类的所有属性,其次对表的设计进行范式化,最后定义数据库的表按时间和空间的权衡。
(2)设计数据管理部分的类,相当于DataManager类,管理其他数据的存储。
6.编程范式
(1)面向过程的程序设计范式,中心思想是设计所需的过程,以及过程的算法,关注的是过程的调用。
(2)模块化程序设计泛型,主要是信息隐蔽,相关的算法和数据结构整合在一个模块中。
(3)结构化程序设计
(4)函数式程序设计
(5)逻辑程序设计
(6)面向对象的程序设计
-
敏捷软件开发
敏捷开发是一种应对快速变化的需求的一种软件开发能力。相比于非敏捷,更强调程序员团队与业务专家之间的紧密协作、面对面的沟通、频繁交付新的软件版本,紧凑而自我组织的团队,可以很好的适应需求变化的代码编写和团队组织方法,也更注重软件开发中人的作用。团队中每个人都参与设计开发工作。
之前软件开发的组织流程太复杂了,业界专家组织起敏捷联盟,概括出一些可以让软件开发团队具有快速工作,响应变化能力的价值观和原则。
敏捷联盟宣言,
(1)个体和交互 胜过 过程和工具
团队中人是获得成功的最重要因素,团队中合作和沟通很重要。
(2)可以工作的软件 胜过 面面俱到的文档
文档不在于多,而在于关键信息要规范。团队中需要维护一份系统原理和结构方法的文档。
(3)客户的合作 胜过 合同谈判
客户的沟通和反馈比合同的约定重要,有助于开发。
(4)响应变化 胜过 遵循计划
详细计划不能做太远。 -
敏捷原则
(1)尽可能早地,持续性交付有价值的软件,让客户满意。
(2)即使到了开发后期,也欢迎改变需求。
(3)经常交付可工作的软件,时间越短越好,可以是几周 几个月。一般是2周
(4)项目期间开发人员和业务人员要在一起工作。
(5)给开发团队给与必要的支持和信任。
(6)团队中最有效的沟通方式是面对面的交流。
(7)首要的进度度量标准是工作的软件
(8)敏捷过程提倡可持续的开发速度。团队应该能保持一个长期的,恒定的开发速度。
(9)不断关注优秀的技能和设计,增强敏捷能力。
(10)简单是根本的,
(11)最好的体系结构、需求和设计出自自己组织的团队。
(12)每隔一段时间,团队要自我反省,进行调整。 -
极限编程
极限编程(extreame programming XP)是敏捷方法中最显著的一个, 由一系列简单而又相互依赖的实践组成。
(1)客户要作为团队的成员,相互了解所面临的问题,共同解决问题。
(2)用户素材(user Stories),为了了解与项目需求有关的内容,采用用户素材来作为需求谈话时的记录,也包含需求的估算。
(3)短的交付周期,每隔两周交付一次,保障客户尽快看到成功。
(4)验收测试,写一些脚本,可以自动反复的验证用户素材的细节。
(5)结对编程,共同设计,共同编写,功劳均等,促进知识在全队的传播。
(6)测试驱动开发,先编写单元测试,再编写功能代码,为了通过测试代码而编写的代码,称之为可测试的代码。
(7)集体所有权,每个结对都有权限检出check out任何代码,没有程序员对一个特定模块单独负责,每个人都可以参与。
(8)持续集成:程序员每天可以多次检入check in ,将他们的模块合并入项目中,要确保所有的测试都能通过。
以上都是极限编程中一些指导性的意见,极限编程一般用面向对象的方法作为推荐的开发泛型,包含策划、设计、编码、测试等环节。
-
Scrum模型