“ 大家好,这是【产品线工程(PLE)专题】更新的第四篇,上一篇我们介绍了‘版本、变体和其他的基础定义’,这一篇我们介绍特征模型和特征-这是什么”
非正式地谈论可变性是很有趣的一件事,但最终还是需要以一种“标准”的方式来捕获可变性的信息。在研究和工业界中有很多方法来捕获可变性信息,其中较流行的方法被称为特征建模。本文将对特征模型的基本概念进行解释,并且对于回答“什么是特征?”这个有趣的问题给出一些提示。
? pure-systems GmbH
问题空间的特征
简而言之,特征模型是简单的、分层的模型,其可以捕获到产品线的共性和特异性。问题空间(Problem Space)中的每个相关特性都会成为特征模型中的一个特征。这意味着,特征是系统中与利益攸关者(Stakeholder)相关特性。根据利益攸关者的利益不同,一个特征可以是一个需求、一个技术功能、一个功能组,或一个非功能(质量)特征。坏消息是:特征模型是一个用于描述共性和特异性的抽象概念。需要为每条产品线单独决定特征究竟是什么。不过,特征的定义一般是与它们的实现是解耦的,即与解空间(Solution Space)解耦。
例如,如果汽车颜色是一个特征,其有个不错的名字“深海蓝”。这个名字永远不会提到特定的油漆供应商的订单号。这是因为特定的供应商与其订单号是存在于解空间的。对软件来说也是一样的:特征是映射到单个功能还是分布在数十个组件中,是无关紧要的。如果利益攸关者认为它是一个相干的属性并且其代表了特异性,那么它就是一个特征。
特征树和变形类型
特征模型有一个树状结构:特征构成树的节点,可变性由节点之间的弧及其通过变形类型分到的组中表示(译者注:特征是节点,特征之间的关系是边。特征的父节点可以有多个子节点,每个特征都具有变形类型并且会按照变形特征分组)。目前在大多数特征建模方法中,有四种的变形类型可供选择。“强制”(Mandatory)、“可行”(Optional)、“多选一”(Alternative)、“或”(Or)。每个特征可以有多个具有不同变形类型的特征组作为子组(假设某个变形类型子组中特征总数为n)。在进行某一个变体的特征选择时,规则为:当一个父特征在该变体中被选择时,其子特征中:
?? 所有“强制”类的子特征必须被包含(n from n)
?? 选择任何数量的“可选”类的子特征(m from n,0≤m≤n)
?? 必须从“多选一”类的子特征中准确地选择一个特征(1 from n)
?? 至少有1个类型为“或”类的子特征被选择(m from n,m≥1)
显然,所有这些术语(例如可选或多选一)都被映射到一个可以被有效选择的特征组的上下限上(译者注:可选,0≤m≤n,即上限n,下限0)。上述这四个特殊的例子是较常用的变形类型。一般来说,即使在没有看到形式化的定义时,也可以通过这些词的概念正确的理解(除了“或”,因为人们通常认为它与“多选一”是同义的)。
当层级结构和变形类型还不够的时候
?? 跨树约束
大多数方法都允许您指定附加的约束,譬如特征之间的互斥关系(“正式衬衫”与“粉红色”相冲突)以及需要关系(“正式衬衫”需要“白色”或“黑色”)。如果使用了多个特征模型,这些约束就会横跨树的不同层级,甚至跨树。根据不同的方法和工具,表达这种约束的语言可以是简单的专用语言或普遍可用的语言,如XPath或OCL。这些语言具有不同的表达能力和复杂性。但是,我们应该少用这些约束语言,这是因为约束条件越多,用户就越难可视化和理解模型中的关系。
?? 复用特征子树
一些方法有特征基数的概念,其允许表达特征模型子树的多重性规则。例如,如果您有一个系统,其连接多个可配置的传感器,那么不需要为每个传感器创建一个(结构相同的)特征子树,只需要创建一个特征子树,并给它一个类似于(1-3)的基数声明来表示需要传感器子树至少配置一个,最多配置三个。
特征模型的图形化表达
对于特征模型的图形符号,目前还没有一个统一的标准,因此有许多不同的符号,在文献中,较常用的是原始FODA方法的图形符号的扩展形式。但是在标准文本工具和图形库中使用这种符号时会导致困难,这就是为什么我们中的一些人更喜欢更简单的符号 - 就像我们在pure::variants中使用方式的原因。
什么是好的特征模型?
通过上面给出的特征定义(比较抽象),几乎所有的东西都可以作为一个特征。从某种意义上说,这确实是事实。接下来的问题是:什么是特征?如何才能知道哪些要被选入特征模型?
比较重要的行动是要明确特征模型是针对利益攸关者而制定的。如果特征被终端用户用来定义他们所拥有的独特的产品变体,显然特征必须是容易理解的。一个很好的例子是在大多数汽车制造商在其网站上提供的汽车配置。除了特征名称之外,特征模型的结构也应该遵循终端用户的思路。虽然听起来很简单,但创建这样一个结构实际上是困难的。或者严格的说,这是不可能的。
?? 特征模型结构
创建一个结构较完美的特征模型之所以如此困难,原因在于很多情况下,有不同的方法来对系统进行配置。根据您的用户类型,您可能要寻找一些小的、专业的功能,或者您可能要做一些一般性的决定,例如发动机的类型和尺寸,汽车的颜色等等。虽然一个特征模型确实允许自由导航(它没有规定选择特征的具体顺序),但更一般性的决定是倾向于更接近模型树的根部的,这反过来又会引导用户深入到树的这个部分或那个部分。
?? 一个模型或几个模型
如果有不同的利益攸关者有不同的“语言”怎么办?我们是应该建立多个特征模型(为每一组利益攸关者)还是只为重要的利益攸关者群体建立一个模型(谁是重要的呢)?同样,针对这个问题给出一个明确的答案也是近乎不可能的。您使用的依赖关系越少,则模型越简单越好。对于许多产品线的应用,使用一个特征模型是一个很好的选择。然而,如果产品线的一部分本身形成了另一个独立的产品线,那么多个特征模型几乎是不可避免的。我们可以想象一下,一个在可配置的中间件上运行的应用。中间件的可变性必须使用应用开发者的语言来捕捉,并且应该对所有使用改中间件的应用使用相同的特征模型。在这种情况下,应用领域的变量与中间件领域的变量之间必须有一个映射关系。创建这种映射是应用产品线工程师的责任。在某些情况下,譬如中间件只在一个特定的配置中使用,因此可能没有映射;在其他情况下,映射可能是非常复杂的。例如,如果应用层提供了安全应用操作和非安全应用操作的选择,那么只要选择了“安全应用操作”特征,中间件中的某些功能(如加密支持、基于证书的认证和SSL支持)就必须被启用--除非该应用是为移动电话设计的,因为它不支持基于证书的认证。
?? 颗粒度
另一个需要考虑的方面是特征的颗粒度。如果特征的颗粒度太粗,有效配置的单个实例可能无法足够详细地描述系统,进而无法发挥预期作用;如果特征的粒度太细,那么特征的数量就会增加,管理和维护这些特征的复杂性和工作量也会增加。再一次地,我们考虑一下背景信息:自动产品配置比产品路线图规划和范围需要更详细的信息,同时也需要记得,后续增加细节比删除细节更容易。
?? 迭代的方法
根据我的经验,如果要获得一个好的特征模型,那么较简单的方法就是创建一个,并尝试用它来描述产品线中已知的/设想的产品变体。在大多数情况下,我们很快就会发现现有的一些决定并不是很明智:有时所选择的特征并不能很好地描述可变性(细节水平),或者树状结构是错误的,例如,建模中特征B是特征A的子特征,但是事实上,您也希望能够只选择特征B而不是特征A。
不要怕,这些错误有助于我们在下一轮创建更好的特征模型。在大多数情况下,有问题的是结构而不是特征本身。关于特征和特征模型,还可以写很多,此时我们按下不表,在后续文章中将会介绍。
特征模型的局限性
还有一件事要提:虽然我确实认为特征模型是描述产品线可变性的一种比较重要的技术,但在某些情况下,仅仅靠特征模型是不够的。甚至在某些情况下,特征模型根本不是可行的方法!如果可变性是组合类型,即有许多基本元素(想想用于建造房屋的砖石)可以按照一些正式规则进行组合。这些规则允许使用潜在的无限数量的砖块。那么在这种情况下,特征模型根本不允许您有效地描述这一点。然而,当谈到描述砖石的潜在属性(颜色、砖材料等)时,特征模型就非常适合用于描述可变性。这些只是为了表明:在很多情况下,特征模型只是可行的方法。
作者:Danilo Beuche
翻译:经纬恒润
【产品线工程(PLE)专题】下期预告:产品线配置管理
* 如果您对PLE或pure::variants感兴趣,可以通过拨打电话与我们取得联系,同时还能获得pure::variants30天的试用申请哦~