(零雨其蒙原创 转载请注明)
2007
年
3
月
12
日星期一
第
30
章
用例关联
目标:
以文本和图形两种形式,使用包含(
include
)
和扩展(
extend
)
关联将用例联系在一起。
Include
包含关系
我觉得理解其内涵可以考虑其动机(我发现其实大多数这个行业的理论都可以从考虑其动机开始,这样会更好、更容易的理解),包含关系就是将几个用例中相同部分抽出来,形成一个单独的用例,那么就说那几个用例包含该用例。其实包含的意义在于减少冗余,增加复用,所以在编写用例时出现包含关系应该是一件水到渠成的事情。于是
Fowler
给出了何时使用包含关系的简单且实用的准则
[Fowler03]
:
当在两个或多个独立用例中存在重复,而你想避免这种冗余时,可以使用
包含
关系。
包含
关系的另一个用途是描述异步事件的处理。指的是在任何时候都可以在主场景中插入该动作。
Cockburn
建议:
使用包含关系来处理用例之间的关系是首要原则。
Extend
扩展关系
扩展关系
是当一个用例不便或不能任意在其上添加新功能时创建扩展或附加用例,并且在其中描述,在何处和何种条件下该用该用例扩展某基础用例的行为。相当于一部没用照相机的手机(基础用例),想要添加照相功能,就需要增加一个扩展插件(扩展用例),但是需要在原来手机中提供插入接口(扩展点)。具体例子见
360
页。
批驳和指正一些不正确的做法是
Larman
本书的一个特点,在这一部分他指出“某些用例准则建议使用扩展用例和扩展关系,将有条件行为或者可选行为加入基础用例。这一观点是不正确的。”好的做法是“将其直接写入(基础用例的)
扩展
部分”。增加扩展用例和扩展关系的最现实动机(或者可以说是最好的动机)就是:由于某种原因实在不能在基础用例上进行修改了。
泛化关系
绝大多数情况下不会使用,而且避免过多使用用例关系是好的实践,即便使用了用例关系,也只是在必要时使用简单的包含关系就可以了。用例顾问们共同观测结论是:大量用例关系会导致复杂结果,并且会花费大量徒劳的时间。
第
31
章
领域模型的精化
时间间隔
反映了某些业务对象仅在有限的一段时间内有效者一概念。
包
使用包可以将大的领域模型组织成较小的单元。
概念分类列表
分类
|
示例
|
有形对象
|
CreditCard
,
Check
|
事务
|
CashPayment
,
CreditPayment
|
其他外部的计算机或机电系统
|
CreditAuthorizationService
|
抽象概念
|
|
组织机构
|
CreditAuthorizationService
|
金融、工作、合同、法律事务等的记录
|
AccountsReceivable
|
从用例中识别名词短语
不能机械地从用例中提取概念,应该作出必要的判断和适当的抽象。
Generalization
泛化
泛化是
在多个概念中识别共性和定义超类(普遍概念)与子类(具体概念)关系的活动。
此活动对概念进行分类学意义上的分类,并将其在类层次结构中表示出来。遇到相似的概念,将其组织起来,形成泛化—特化类层次结构(简称类层次结构)。在这里我们讨论的是概念类而非软件类。
什么样的概念子类是正确的?
正确的概念子类应遵守下面两条规则(
规则意味着一定要遵守):
l
100%
规则(定义的一致性)
l
Is-a
规则(集合成员关系的一致性)
定义概念子类的动机
准则
在下述几种情形下创建概念类的子类:
1
)子类有额外的有意义的属性
2
)子类有额外的有意义的关联
3
)子类概念的操作、处理、反应或使用的方式不同于超类或其他子类,而这些方式是我们所关注的。
4
)子类概念表示了一个活动体(例如动物、机器人等),其行为与超类或者其他子类不同,而这些行为是我们所关注的。
有意义和我们所关注的成为了上述准则(也可以说是
Larman
的整体思想)所强调的一个重点,子类的创建一定要创造价值,否则就不要创造它了。而上述准则为我们指明了创造子类的动机,无外乎就是说子类有了新的有意义的属性、关联和方法,需要将其创建出来。
定义概念超类的动机
准则
在下述几种情形下可以创建与子类具有泛化关系的超类:
1)
潜在的概念子类表示的是相似概念的不同变体
2)
子类满足
100%
和
Is-a
规则
3)
所有子类都具有相同的属性,可以将其解析出来并在超类中表达
4)
所有子类都具有相同的关联,可以将其解析出来并与超类关联。
对变化的状态建模
准则
不要将概念
X
的状态建模为
X
的子类。有两个办法可供选择:
1
)定义状态类层次结构,并将其与类
X
关联
2
)在领域模型中忽略概念的状态,而在状态图中加以反映。
关联类
准则
在领域模型中,如果类
C
可能同时有多个相同的属性
A
,则不要将属性
A
置于
C
之中。应该将属性
A
放在另一个类中,并且将其与类
C
关联。
增加关联类的准则
准则
在领域模型中增加关联类的可能线索有:
l
有某个属性与关联相关
l
关联类的实例具有依赖于关联的生命期
l
两个概念之间有多对多关联,并且存在与关联自身相观的信息。
√
这与数据库建模中创建关联是一样的(我暂时如此认为),这样我们可以以同样的观点来理解合适增加关联类(因为数据库建模是我近几年做项目最常用的开始软件分析设计的起点,而学习了本书后,我想领域建模将成为我的起点)。
组合
组合是一种关联关系,这在之前已经讨论过了。但是在这一章补充了组合的一些准则。
使用组合关系的准则
准则
在下述情况下,可以考虑组合关系:
l
部分的生命期在组成生命其界限之内,部分的创建和删除依赖于整体。
l
在物理或逻辑组装上,整体—部分关系很明确
l
组成的某些属性(例如位置)会传递给部分
l
对组成的操作(例如销毁、移动、记录等)可能传递给部分
我的观点:
知道什么时候用比知道是什么更难,而且也更加重要。
受限关联
在关联中可能会用到限定词(
qualifier
)
;基于限定词的值可以区分位于关联另一端的对象集合。具有限定词的关联是受限关联。
在领域模型中
,描述一个限定词所表达出的含义是:如何通过与另一个类的关系来区别某类中的事物。在此模型中不要用限定词表示有关查找关键字这样的设计决策。
自反关联
概念到自身的关联称为自反关联(
reflexive associaition
)。
使用包来组织领域模型
所有权和引用
元素属于包含它的包,但同时也可以被其他包引用。在引用时,需要以包名对元素加以限定,格式是:包名::元素名。对于在外部包(引用元素的包)中所表示的被引用的类,只可以添加新的关联,除此之外都不能改变。(好比说水中映月,你不能改变水中月亮,因为你改变了水中月亮,天上的月亮也不会改变)
包的依赖关系
如果模型元素以某种方式依赖于另一元素,则可以用依赖关系来表示。
如何划分领域模型
准则
将领域模型划分为包结构时,将满足下述条件的元素放在一起:
l
在同一主题领域,概念或目标密切相关的元素
l
在同一类层次结构中的关系
l
参与同一个用例的元素
l
有很强的关联性的元素
第
33
章
架构分析
什么是架构分析?
l
架构分析可以被视为需求分析的规格化,其关注强烈影响“架构”的需求。
l
架构分析的本质是要识别影响架构的因素,理解这些的可变性和优先级,并且解决这些问题。其难点是要知道应该问什么样的问题,权衡利弊和了解处理一个重要架构因素的各种办法,从良性忽略到奇特设计或者第三方产品等。
优秀的架构师的价值在于他们具有知道问什么问题的经验,并且能够熟练选择各种方法来解决这些因素。
l
是在功能性需求(例如处理销售等)的语境中,识别和处理系统非功能性需求(例如安全需求等)的活动。
其包括识别变化点和最具可能性的进化点。
l
在
UP
中,术语“架构分析”既包含架构调查(识别)也包含架构设计(解决)。
变化点和进化点
l
变化点(
variation point
)
——当前现有系统或需求中的变化之外
l
进化点(
evolution point
)
——现有需求中不存在、但可能在将来发生,推测性的变化点。
架构分析的常用步骤
1)
识别和分析对架构有影响的非功能性需求。
2)
对于这些架构方面具有重要影响的需求,需要分析可供选择的办法并创建解决这些影响的解决方案。这就是架构决策。
因素表
因素
|
度量和质量场景
|
可变性
(
当前的灵活性和未来的演化性
)
|
该因素对涉众、架构以及其他因素的影响
|
对于成功的优先级
|
困难或风险
|
可靠性和可恢复性
|
|
|
|
|
|
|
可支持性和可适用性
|
|
|
|
|
|
|
因素表是用例补充规格说明的一部分。它主要用来帮助架构师理解架构性因素的影响、优先级和可变性(立即需要的灵活性和未来的演化)。度量场景主要是将一些因素量化。
关注分离
实现关注分离的几个大尺度的技巧:
1)
将有关事务模块化,封装到单独的构件(例如子系统)中,并调用其服务
2)
使用装饰者
3)
使用后编译器和面向方面技术。
在
UP
中,架构的逐步演化和稳定是通过早期的以架构为核心的开发和测试,而不是通过纸上谈兵或者“
PowerPoint
架构”来完成的。
UP
制品中的架构信息
l
架构性因素(例如因素表中的因素)被记录在补充规格说明中
l
架构性决策被记录在
SAD
(软件架构文档)中。这其中包含技术备忘录和架构视图的描述。
第
34
章
逻辑架构的精化
使用层模式的协作
首先层模式就是我们熟悉的分层架构!
简单包与子系统
某些包和层不仅仅是概念上的一组事物,事实上它们是具有行为和接口的子系统。
外观
对于表示子系统的包,
GoF
外观(
Facade
)模式是最常用的访问模式。一个公共的外观对象定义了子系统的服务,客户端不与子系统内部的构件交互,而是通过与外观对象协作来访问子系统。
会话外观和应用层
当系统不断增长,需要处理许多用例和系统的操作时,则通常会引入应用层的对象来维护用例操作的会话状态,每个会话实例表示与一个客户的会话。这被称为会话外观(
Session Facade
)。
应用层
:如果存在应用层,则其应作为
UI
层和领域层之间的中介,容纳负责获知客户会话状态的对象,并且负责控制工作的流程。
松散分层耦合关系
有关层之间的典型耦合有下面的注解:
l
所有较高层都依赖于技术服务层和基础层。
l
领域层依赖于业务基础设施层。
l
UI
层调用应用层的服务,应用层又调用领域层的服务。除非没有应用层,否则
UI
层不直接调用领域层的服务
l
对于单进程的“桌面”应用,领域层的软件对象对于
UI
层、应用层(某种程度上,还有技术服务层)可见(可见就是说
UI
层或应用层能调用领域层对象),或者在上述各层之间传递(指的是领域层对象可以被传递到
UI
层展示数据或传递到技术服务层中的持久性子系统中)
l
另一方面,在分布式系统中,通常将领域层对象的序列化副本(也称为值对象(
value object
)
)或数据持有者(
data object
)传递给
UI
层。在此情况下,领域层部署在服务器上,客户节点得到服务器数据的副本。
基础设施层
将技术服务层和基础层看成一组,称为基础设施层