ADD3.0属性驱动设计总结
属性驱动设计是目前最全面最广泛使用的有文档记录的软件架构设计方法,简称ADD。在ADD第一次出现时,他是一个特别侧重于质量属性,并且通过创建软件架构的结构方式来实现他们,通过视图来表示他们的设计方法。它把软件架构分析和文档作为设计过程的一个重要组成部分。在ADD中,设计活动包括提炼早期设计迭代过程中创建的草图来产生一个更详细的架构,并不断对设计进行评估。
在ADD2.0发布时,对于如何将质量属性和设计选择相关关联起来非常有用,但仍旧有一些缺点:
- ADD2.0指导架构师使用并将策略和模式组合在一起以实现令人满意的质量属性场景,但是模式和策略比较抽象,没有解释如何去映射成具体的技术
2.ADD2.0在敏捷开发之前发布,所以没有关于敏捷开发环境的指导。 - 没有提供如何开始设计过程的指导。
- 没有处理一些架构关注点、考虑不同的设计目标。
。。。。
在ADD3.0中,以上的这些都解决了,对于敏捷开发中,ADD3.0推广的是快速设计迭代,在每个迭代尽量做出少的设计决策,可能是一个实现的重建增量。
在ADD3.0中推广了使用参考架构,并与设计概念目录配对,该目录中包括一个各种战术,模式,框架,参考架构和技术的选集。
在看这篇文章之前,里面有很多专业性名词解释,建议先看下这篇文章,对一些架构相关和属性驱动设计相关的概念能有一个入门性的认识,方便后面的学习:
ADD3.0属性驱动设计之基础
属性驱动设计的架构设计过程
1.步骤一: 评审输入
首先需要确保设计流程的输入是可用且正确的,先确认设计目的是否符合设计的类型,确保设计过程中其他的属性驱动因子也是可用的,最后,如果是设计一个绿地系统,还需要已经存在的架构设计的输入存在是否合理。
(注: 架构驱动因子包含: 设计目的、质量属性、主要功能、架构关注点、约束条件等等,详情我后面会说)
驱动因子成了架构设计待办列表的一部分,需要用他们来完成不同的迭代目标。
2.步骤二: 通过选择驱动因子(架构)建立迭代目标
根据使用的开发模型去选择设计的回合。
如果是迭代开发模型,设计回合指在开发周期内所执行的架构设计活动,如果是瀑布模型,设计回合指代的是全套架构设计活动。通过一个或者多个回合,产生一个符合已建立设计目的架构。
一个设计回合需要在一系列的设计迭代中进行,每一个迭代着重完成一个目标,特别是满足驱动因子的目标。举个例子: 一个迭代的目标可能是创建源自元素的结构,这些元素会支持特殊的性能场景,或者启动一个即将完成的用例。
3.步骤三: 选择一个或者多个系统元素来细化
(注: 这里的元素是指软件模块、整个软件系统包含多少个元素或者说子模块,电商软件系统: 订单、库存、支付、前台、用户等等元素)
需要满足驱动因子需要产生一个或者多个架构结构,这些结构是由具有内在关联的元素组成的,并且这些元素通常是经过细化前在之前的迭代中确定的元素获得的。
细化就是分解成细粒化的元素、组合成粗粒度的元素或者对之前确定好的元素进行细化。
4.步骤四: 选择一个或者多个设计概念(就是架构设计模式)以满足选中的驱动因子.
架构设计模式包括结构模式: 分层设计、域对象设计。接口分区:显示接口,代理。 基于高并发得设计: 半异步/半同步设计。后面会详细介绍。
5.步骤五:实例化架构元素、分配职责和定义接口
选择好了一个或者多个设计概念,就要另作一个设计决策了,包括所选择的实例化元素的设计概念。如果选择分层,需要决定分多少层,在这里例子中,这些分层就是实例化后的元素,某些情况下,实例化是可以配置的。
在实例化元素之后,需要给每个元素分配职责。举个例子: 在据于网络的企业级系统中,通常有三层:表示层、业务层、数据层。
实例化元素只是一个任务,这个任务通过开展创建架构以满足一个驱动因子或者一个关注点。已经被实例化后的元素也需要被关注起来,一遍这些元素之间可以互相配合。通过接口来实现交互。
6步骤六: 草拟视图和记录设计决策
到了这一步,已经完成了该迭代中所执行的设计活动了。可能你还没有采用任何行动来确保结果视图能够被保留。你创建好的视图肯定不是完整的,在随后的迭代中这些图可能还需要重新被审视和细化。通常这样做是为了调整其他设计决策产生的元素,这些设计决策还需要支持其他的驱动因子,这个就解释了,我们在ADD方法中,强调手稿,代表创建初期。
7:步骤七: 分析当前设计、评审迭代目标、实现设计目的
目前已经创建好了部分设计,此时已经可以得到这个迭代设计建立的目标。徐奥确保这个目标是一个好想法,可以得到项目利益相关者的认同,避免否定,导致返工。此时可以自己继续展开分析或者找人帮助评审。
一旦在迭代中执行的设计进行了分析,此时你就可以根据既定的目标来评审你的架构状态。这意味着,你已经进行了足够的设计迭代,已满足与设计回合相关的驱动因子,以及考虑设计目标是否已经实现了,或者在未来项目增量中,是否需要额外的回合。
最后一步: 按需迭代
理想状态下,对每一个被称为输入组成之一的驱动因子,都要执行额外的迭代,并重复执行步骤2-7.通常情况下,这样的迭代不太可能出现,因为时间或资源的限制,会迫使你停止设计活动。
对于是否需要更多的迭代,可以让风险来评估。怎么说呢?我们至少找到更高优先级的驱动因子,理论上,应该确保关键驱动因子是被满足的,或者至少设计了足够好的满足驱动因子,最后实施时,能够在每个项目迭代中,执行一个设计回合。第一回合把重点放在定位驱动因子上,随后再为其他回合指定设计决策。
根据系统设计类型遵循设计路线图
一般来说,软件系统的设计分为三大类:
1. 一个成熟领域内的绿地系统设计。
举个例子: 比如非常常见的电商购物系统、CRM等企业级系统,都是在领域内很成熟的,并且常见的架构关注点也总所周知,十分常见。可以按照上图的步骤来实现。
最初的迭代目标应该是,解决建立一个初步完整的整体系统体系架构的常见关注点,是一个浏览器到服务器的一个应用程序或者移动端到服务端。这些选择会让你建立不同的架构解决方案,并且这些解决方方案将有不同的实现驱动因子。
具体而言,为了实现设计目标,,需要选择设计概念,会选择一个或多个参考架构和部署模式,还有一些外部开发组件比如spring框架等。
在第一期迭代,需要评审所有的驱动因子来选择设计概念,也需要注意约束条件和质量参数。
接着的迭代目标,应该是识别那些支持主要功能的结构,对功能进行分配,一旦功能被分配好了,支持功能的元素可以在之后的迭代阶段,支持与这些功能关联的质量参数。例如选择一个web应用程序参考体系结构,支持的用例可能需要识别模块,这些模块贯穿在与参考架构关联的不同分层中,最后,在这一点上,也应该考虑哪些与模块相关的功能分配,要分配到开发团队中去。
之后的迭代目标,应该是完善细化之前创建的结构,以完全解决剩余的驱动因子,特别是质量属性。
2. 一个新领域内的绿地系统设计。
在新兴领域的例子中,比较有挑战性的是建立一个精确的路线图。这块的设计路线图,没办法详细说明,还是基于属性驱动设计的思路:
迭代的目标主要还是不断完善和细化以前创建的结构,以充分解决这些驱动因子。
3.对现有系统的更改设计(棕地系统设计)。
现存系统架构设计的目的不同,最显而易见的是保留,就是说在满足新需求和修复bug的时候,需要改变现有的系统架构,我们在ADD方法的步骤三中说明了,需要选择元素已将其分解为设计过程的一部分,首先需要确定哪些元素存在于现有的系统架构中,从这个意义来说,在开始设计迭代之前,第一个目标,需要先对现有系统的架构有非常清晰的认识。
一旦你理解了元素、属性、构成系统架构的关系,以及现存代码库的属性,在初始设计迭代之后,就可以执行类似于下面面对绿地系统的设计。
设计目标应该是确定和改进结构,以满足架构驱动因子,包括新的功能和质量参数,以及解决特定的架构问题关注点,包括新的功能和质量参数,以及解决特定的架构问题。
如何设计和选择设计概念
设计概念的识别是很艰难的,因为世界上有很多的设计概念,可能有几十个设计模式和外部开发组件,能够用来解决特定的具体问题。
在设计过程中的不同环节一般需要不同类型的设计概念,比如设计成熟领域的绿地系统时,有助于初步构建系统设计概念类型的是参考架构和部署模式。
随着设计过程的进行,将使用所有的设计概念类型: 决策,架构和设计模式、外部开发组件。一般来说,为了解决一个特定的设计问题,都会使用各种不同的设计概念组合起来。
一旦对需要使用的设计概念有清晰的理解之后,还需要一个确认一个替换方案---就是设计的候选方案。
在识别和选择设计概念时,也要考虑约束因子,这也是架构驱动因子的一部分,某些条件可能会限制你选择特定的替换方案。
最后还需要记住,ADD这种方式只是对如何执行设计过程提出了指导,并不意味着能确保你做出合适的设计决策。
架构结构的生成
设计概念对满足驱动因子本身没有帮助,除非构建出架构来,也就是说,需要识别并选定设计概念的元素,在ADD方法中,这个过程其实就是架构元素实例化,建立元素与元素之间的关系,给这些元素分配不同的职责.需要清楚,一个软件系统应该是由一组结构组成的,这些结构可以分成三大类:
1、模块结构
由开发期间的逻辑和静态元素组成,如文件、模块以及类。
2、组件和连接器结构
由运行时存在的动态元素组成,如进程和线程
3、分配结构
由两个软件元素(来自于C&C结构)以及非软件元素组成,非软件元素一般存在于开发期间也存在
于运行期间,如文件系统、硬件以及开发团队。
实例化设计概念时,可能生成不止一个结构。例如,在某个特定的迭代中,实例化分层模式,生成一个模块结构。作为实例化该模块的一部分,选择分层数量、层与层之间的关系,以及每一层的职责,作为迭代的一部分,也可以研究场景是如何由元素支撑起来的,这些元素就是你刚刚确定下来的那些。例如,可以在C&C建立一个逻辑元素的实例,模拟逻辑元素交换的信息。最后要决定谁来负责实施每一层内的模块,称之为分配决策。
需要以下步骤:
1. 把架构元素实例化
架构元素方面的实例化,取决于你正在制定的设计概念的类型:
参考架构: 在参考架构的情况下,实例化就需要实施某些定制化,增加或者删除某些元素。比如如果是个web应用程序,在处理支付相关操作时,需要跟一个外部应用程序进行通信,除了正常的MVC层之外,还需要一个集成层。
架构和设计模式: 实例化通常涉及到由模式定义的通用结构的转换,转换到特定的结构。
部署模式:部署模式的实例化通常涉及物理元素的识别和规范,比如部署的集群的数量,负载均衡策略,算法,和副本的位置等等。
策略: 策略这个设计概念没有特定的结果,所以需要使用其他设计概念来实例化策略,比如你选择一种角色验证的安全策略,可以创建一个临时编码来实例化该策略,也可以通过安全模式或者使用外部开发安全框架来实现。
第二步: 划分职责和识别属性
通过实例化设计概念和创建元素时,需要考虑给这些元素分配职责。比如如果是实例化分层模式并且使用传统的三层时,还需要考虑其中一个分层负责处理用户交互,这是表示层,在实例化元素和分配职责时,切记系统边界的问题,高内聚/低耦合的设计原则,元素需要具有高内聚,比如通过小范围的职责定义,还要保持低耦合,不用通过了解其他元素来实现业务细节。
在设计化实例概念时,需要考虑另一个方面的元素的属性,这可能包括比如一些配置的选项,状态性,资源管理,优先级,识别这些属性来帮助分析和维持设计原理文档。
最后要建立元素之间的关系
架构创建还需要对元素和元素属性之间存在的关系做出决策。然后,可以考虑分层模式。你可以决定把两层连接起来,但是这些层,终将会分配在不同的机器上,此时你可以涉及如何进行通信,选择的哪种通信协议,进行异步通信还是同步通信?这些都会对生成的具体的质量属性有明显的影响,如性能等属性。
设计过程中第五步: 定义接口
接口是我们元素的外部可见属性,这些元素建立了一个允许元素合作和交换信息的规范。接口有两种类型: 内部的和外部的。
外部接口: 正在开发的系统需要其他外部的其他系统提供的接口,以及我们提供给外部系统的接口。
内部接口是设计实例化概念设计结构产生的元素之间的接口,要实现接口间的关系和细节,通常需要了解运行时如何交换信息,这需要建模工具来理解,可以使用UML工具中的序列图来对执行过程中元素的交互信息进行建模,来支持用例和质量属性方案,这种类型的分析也有利于识别元素间的交互关系。