模块 8:变体与配置
如何定义变体点、声明可选变体并配置产品线 — 让一个模型就能刻画整个系统配置族。
KerML → SysML:可变性概念
SysML v2 的可变性建立在 KerML 的使用变体(usage variation)与变体成员关系(variant membership)机制之上。variation 使用声明一个可变点 — 该特征必须恰好绑定到其允许的备选项之一。变体点内的每个 variant 都是一个独立的成员选项。在 KerML 层面,这些都通过使用上的特征成员关系与子集关系来建模。
| SysML v2 概念(L2) | 底层 KerML 构造(L1) | SysML 增加了什么 |
|---|---|---|
variation(作用于使用) | isVariation = true 的 Usage | 把某个特征标记为变体点;在任何完整配置中都必须解析为恰好一个变体 |
variant | VariantMembership(一种 OwningMembership) | 在变体点内声明一个具名备选项;每个变体都是该变体使用的子集 |
variation part def | isVariation = true 的 PartDefinition | 其使用天然即为变体点的定义 — 每次使用都必须被解析 |
variant(位于变体定义内) | 拥有某个使用的 VariantMembership | 在变体定义中充当一个选项的使用 |
| 配置绑定 | 把变体解析到某个具体变体的 BindingConnector | 固定该选择;产出一个完整解析的产品实例 |
filter 表达式 | FilterExpression(作用于元数据的布尔表达式) | 依据元数据条件从包或命名空间中挑选元素 |
| 产品线包 | 混合了变体与非变体内容的 Package | 把共享平台元素与产品族的变体点组织在一起 |
在 KerML 中,isVariation 是任意 Usage 上的布尔属性。当它为 true 时,该使用即成为变体点,其带 VariantMembership 的自有成员就是允许的选项。SysML v2 用 variation 与 variant 关键字为这套机制提供了语法糖。
变体点
KerML 起源:variation → isVariation = true 的 Usage
变体点是模型中代表一次选择的特征 — 不同配置正是在这里产生差异。在 SysML v2 中,给使用加上 variation 前缀即可声明变体点。变体使用本身并不是具体元素,而是一个占位符:在任何完整配置中,它都必须被解析为某一个变体。
可以想象一份餐厅菜单。菜单上的「主菜」这一栏就是变体点 — 每位客人必须且只能选一项。具体的菜品(牛排、鱼、意面)则是变体。菜单定义结构,而每位客人点的那一单就是一个配置。
零件使用上的变体
最常见的变体形式作用在零件定义内的零件使用上。variation 关键字声明该特征是一个可变点,variant 成员则声明允许的备选项:
1 part def Vehicle {
2 part engine : Engine;
3
4 // Variation point: transmission type
5 variation part transmission : Transmission {
6 variant part manual : ManualTransmission;
7 variant part automatic : AutomaticTransmission;
8 variant part cvt : CVTTransmission;
9 }
10 }
在这个模型中,每个 Vehicle 实例都必须恰好有一套变速器 — 手动、自动或 CVT 三者取一。变体点不是可选项,它强制要求作出选择。
属性使用上的变体
变体点并不限于零件。你可以把它用在属性、端口或任何其他种类的使用上:
1 part def Display {
2 // Variation point: screen resolution
3 variation attribute resolution : ScreenResolution {
4 variant attribute hd : HD; // 1280x720
5 variant attribute fhd : FHD; // 1920x1080
6 variant attribute uhd : UHD; // 3840x2160
7 }
8 }
变体点必须至少包含一个 variant 成员。声明一个没有任何变体的 variation 使用属于语义错误 — 因为根本无从选择。工具应把它标记为不完整。
变体定义
KerML 起源:variant → VariantMembership(一种 OwningMembership)
变体是变体点内的一个具体备选项。每个变体都是完整规定的元素 — 它带有自己的特征、约束和子结构。当某个配置选中一个变体时,在解析后的模型中,该变体的完整定义就取代了原来的变体点。
内联变体定义
变体可以直接内联定义在变体点里,并带上各自特有的特征:
1 part def Powertrain {
2 variation part motorType : Motor {
3 variant part ice : ICEMotor {
4 attribute displacement : ISQ::VolumeValue;
5 attribute cylinders : ScalarValues::Integer;
6 }
7 variant part electric : ElectricMotor {
8 attribute peakPower : ISQ::PowerValue;
9 attribute batteryCapacity : ISQ::EnergyValue;
10 }
11 variant part hybrid : HybridMotor {
12 attribute displacement : ISQ::VolumeValue;
13 attribute peakPower : ISQ::PowerValue;
14 }
15 }
16 }
引用外部的变体定义
变体也可以引用单独定义的零件定义。当同一个变体出现在模型中多个变体点里时,这种写法很有用:
1 part def ManualTransmission :> Transmission {
2 attribute gearCount : ScalarValues::Integer;
3 }
4
5 part def AutomaticTransmission :> Transmission {
6 attribute modes : DriveMode[1..*];
7 }
8
9 part def Vehicle {
10 // Variants reference externally defined part defs
11 variation part transmission : Transmission {
12 variant part manual : ManualTransmission;
13 variant part automatic : AutomaticTransmission;
14 }
15 }
变体定义(定义级)
你也可以用 variation part def 把整个定义标记为变体。这意味着该定义本身是抽象的 — 它不能被直接实例化,而必须解析为它的某个变体成员:
1 variation part def DriveMode {
2 variant eco : EcoMode;
3 variant sport : SportMode;
4 variant normal: NormalMode;
5 }
要区分作用在使用上的 variation 与作用在定义上的 variation。变体使用是一个必须在上下文中被解析的具体特征;变体定义则声明类型本身就是一个变体 — 该定义的每一次使用都继承变体点语义。
配置管理
KerML 起源:配置绑定 → 把变体解析到某个具体变体的 BindingConnector
配置是对模型中全部变体点的一次具体解析。它为每个变体点恰好选定一个变体,从而产出一个完整规定的产品实例。在 SysML v2 中,配置通过特化产品定义、并把每个变体使用绑定到所选变体来建模。
通过特化创建配置
标准做法是新建一个零件定义或使用,特化那个可变的产品,并绑定每一个变体点:
1 // Base product with variation points
2 part def Vehicle {
3 part engine : Engine;
4 variation part transmission : Transmission {
5 variant part manual : ManualTransmission;
6 variant part automatic : AutomaticTransmission;
7 }
8 variation part infotainment : Infotainment {
9 variant part basic : BasicInfotainment;
10 variant part premium : PremiumInfotainment;
11 }
12 }
13
14 // Configuration: Sport Edition
15 part def SportEdition :> Vehicle {
16 // Resolve transmission to manual
17 part transmission redefines Vehicle::transmission = transmission::manual;
18 // Resolve infotainment to premium
19 part infotainment redefines Vehicle::infotainment = infotainment::premium;
20 }
21
22 // Configuration: Economy Edition
23 part def EconomyEdition :> Vehicle {
24 part transmission redefines Vehicle::transmission = transmission::automatic;
25 part infotainment redefines Vehicle::infotainment = infotainment::basic;
26 }
部分配置
并非每个配置都必须解析全部变体点。部分配置只解析其中一部分,其余保持开放。这在为产品档次或区域变体建模时很有用 — 某些选择已经固定,另一些仍需灵活:
1 // Partial configuration: European variant (fixes transmission, leaves infotainment open)
2 part def EuropeanVehicle :> Vehicle {
3 part transmission redefines Vehicle::transmission = transmission::manual;
4 // infotainment variation point remains unresolved
5 }
6
7 // Full configuration: European Sport (resolves remaining variation)
8 part def EuropeanSport :> EuropeanVehicle {
9 part infotainment redefines Vehicle::infotainment = infotainment::premium;
10 }
可以用部分配置搭建分层的配置体系:从基础产品出发,先做区域级或档次级的部分配置,再在叶节点做完全解析的配置。这与汽车主机厂在实践中管理产品线的方式一致。
过滤与选择
KerML 起源:filter → FilterExpression(作用于元数据的布尔表达式)
过滤表达式提供一种查询机制,可依据元数据条件从命名空间中挑选元素。与直接的变体绑定不同,过滤器可以跨包工作,并能同时选中多个元素。它与元数据注解配合使用时尤其强大。
基本过滤语法
filter 表达式是施加于包内元素的布尔谓词。只有满足该谓词的元素才会出现在过滤后的视图中:
1 // Metadata for tagging elements
2 metadata def Region {
3 attribute name : ScalarValues::String;
4 }
5
6 metadata def Tier {
7 attribute level : ScalarValues::String;
8 }
9
10 package AllFeatures {
11 part heatedSeats : HeatedSeats {
12 @Region { name = "EU"; }
13 @Tier { level = "premium"; }
14 }
15 part airCon : AirConditioning {
16 @Region { name = "ALL"; }
17 @Tier { level = "basic"; }
18 }
19 part sunroof : PanoramicSunroof {
20 @Region { name = "US"; }
21 @Tier { level = "premium"; }
22 }
23 }
应用过滤表达式
过滤表达式依据元数据从包中挑选元素。被过滤的包充当一个视图 — 它并不复制元素,而是给出一个受限的子集:
1 // Select only premium-tier features
2 package PremiumFeatures {
3 import AllFeatures::**;
4 filter @Tier and Tier::level == "premium";
5 }
6
7 // Select only EU-region features
8 package EUFeatures {
9 import AllFeatures::**;
10 filter @Region and (Region::name == "EU" or Region::name == "ALL");
11 }
过滤表达式作用于元数据注解。它们不会修改底层模型 — 只是产出一个仅含匹配元素的模型视图。这在概念上类似数据库查询:数据本身没变,只是结果集被收窄了。
把过滤器与变体结合使用
过滤器与变体点是互补机制。变体点定义的是强制选择(必须选一个);过滤器定义的是可选纳入(满足条件才纳入)。设计良好的产品线两者兼用:
- 变体点用于结构性备选(发动机类型、车身形式)
- 过滤器用于功能包(舒适选装、区域合规功能)
不要用过滤器替代变体点。过滤器是从既有集合中挑选,变体点则声明一次强制选择。如果每个产品都必须在若干备选中恰好取一个,请用 variation/variant;如果某项功能是依据元数据有条件地纳入,才用 filter。
产品线建模
KerML 起源:产品线 → 混合了变体与非变体内容的 Package
产品线是一族共享同一平台、但在具体功能上有所差异的产品。SysML v2 通过共享定义(平台)、变体点(可配置的部分)与配置(已解析的产品)三者的组合来支持产品线建模。
平台 + 变体策略
推荐的模式把模型分为三层:
- 平台包 — 共享定义、不变结构与公共约束
- 可变性包 — 变体点与变体定义
- 配置包 — 绑定了全部变体点的完整产品
1 package Platform {
2 // Shared across all products
3 part def Chassis { attribute wheelbase : ISQ::LengthValue; }
4 part def BrakeSystem { part frontBrakes : DiscBrake; part rearBrakes : DiscBrake; }
5 part def SteeringSystem { attribute ratio : ScalarValues::Real; }
6 }
7
8 package Variability {
9 private import Platform::*;
10
11 part def ProductVehicle {
12 part chassis : Chassis; // from platform (invariant)
13 part brakes : BrakeSystem; // from platform (invariant)
14 part steering : SteeringSystem; // from platform (invariant)
15
16 // Variable aspects
17 variation part body : BodyStyle {
18 variant part sedan : SedanBody;
19 variant part suv : SUVBody;
20 variant part truck : TruckBody;
21 }
22 variation part powertrain : Powertrain {
23 variant part petrol : PetrolPowertrain;
24 variant part diesel : DieselPowertrain;
25 variant part electric : ElectricPowertrain;
26 }
27 }
28 }
29
30 package Configurations {
31 private import Variability::*;
32
33 part def SedanPetrol :> ProductVehicle {
34 part body redefines ProductVehicle::body = body::sedan;
35 part powertrain redefines ProductVehicle::powertrain = powertrain::petrol;
36 }
37
38 part def SUVElectric :> ProductVehicle {
39 part body redefines ProductVehicle::body = body::suv;
40 part powertrain redefines ProductVehicle::powertrain = powertrain::electric;
41 }
42 }
约束在变体间的传播
定义在平台或基础产品上的约束适用于全部配置;变体特有的约束则可以加在变体层级上:
1 part def ProductVehicle {
2 // Platform constraint: applies to ALL configurations
3 assert constraint maxWeight {
4 chassis.totalMass <= 2500[kg]
5 }
6
7 variation part body : BodyStyle {
8 variant part truck : TruckBody {
9 // Variant-specific constraint: only applies when truck is selected
10 assert constraint towingCapacity {
11 payloadCapacity >= 1000[kg]
12 }
13 }
14 }
15 }
三层模式(平台、可变性、配置)具有良好的可扩展性:平台包可由平台工程团队维护,可变性包由产品管理负责,配置包则由各产品团队负责。每一层从下一层导入内容。
完整示例
下面的模型整合了本模块的全部概念:一条车辆产品线,包含轿车、SUV 与皮卡三种变体,共享同一平台,各自具备动力总成与功能级的可变性,并配有元数据驱动的过滤和完整解析的配置。
1 package VehicleProductLine {
2 private import ISQ::*;
3 private import SI::*;
4 private import ScalarValues::*;
5
6 // ── Metadata for filtering ──────────────────────────────
7 metadata def MarketRegion {
8 attribute region : String;
9 }
10 metadata def FeatureTier {
11 attribute tier : String;
12 }
13
14 // ── Shared platform ─────────────────────────────────────
15 part def Chassis {
16 attribute wheelbase : LengthValue;
17 attribute curbWeight : MassValue;
18 }
19 part def BrakeSystem {
20 part frontBrakes : DiscBrake;
21 part rearBrakes : DiscBrake;
22 part abs : ABSController;
23 }
24 part def SteeringSystem {
25 attribute steeringRatio : Real;
26 }
27
28 // ── Body style variants ──────────────────────────────────
29 part def BodyStyle;
30 part def SedanBody :> BodyStyle {
31 attribute doorCount : Integer = 4;
32 attribute trunkVolume : VolumeValue;
33 }
34 part def SUVBody :> BodyStyle {
35 attribute doorCount : Integer = 5;
36 attribute groundClearance : LengthValue;
37 attribute roofRails : Boolean = true;
38 }
39 part def TruckBody :> BodyStyle {
40 attribute doorCount : Integer = 4;
41 attribute bedLength : LengthValue;
42 attribute payloadCapacity : MassValue;
43 }
44
45 // ── Powertrain variants ──────────────────────────────────
46 part def Powertrain;
47 part def PetrolPowertrain :> Powertrain {
48 attribute displacement : VolumeValue;
49 attribute cylinders : Integer;
50 attribute maxPower : PowerValue;
51 }
52 part def DieselPowertrain :> Powertrain {
53 attribute displacement : VolumeValue;
54 attribute maxTorque : ForceValue;
55 }
56 part def ElectricPowertrain :> Powertrain {
57 attribute batteryCapacity : EnergyValue;
58 attribute range : LengthValue;
59 attribute chargePower : PowerValue;
60 }
61
62 // ── Optional feature packages (metadata-tagged) ─────────
63 package FeatureCatalog {
64 part heatedSeats : HeatedSeats {
65 @MarketRegion { region = "ALL"; }
66 @FeatureTier { tier = "premium"; }
67 }
68 part adaptiveCruise : AdaptiveCruiseControl {
69 @MarketRegion { region = "ALL"; }
70 @FeatureTier { tier = "premium"; }
71 }
72 part towHitch : TowHitch {
73 @MarketRegion { region = "US"; }
74 @FeatureTier { tier = "basic"; }
75 }
76 part headlightWashers : HeadlightWashers {
77 @MarketRegion { region = "EU"; }
78 @FeatureTier { tier = "basic"; }
79 }
80 }
81
82 // ── Base product with variation points ───────────────────
83 part def Vehicle {
84 // Platform (invariant across all configurations)
85 part chassis : Chassis;
86 part brakes : BrakeSystem;
87 part steering : SteeringSystem;
88
89 // Variation point 1: body style
90 variation part body : BodyStyle {
91 variant part sedan : SedanBody;
92 variant part suv : SUVBody;
93 variant part truck : TruckBody;
94 }
95
96 // Variation point 2: powertrain
97 variation part powertrain : Powertrain {
98 variant part petrol : PetrolPowertrain;
99 variant part diesel : DieselPowertrain;
100 variant part electric : ElectricPowertrain;
101 }
102
103 // Platform constraint: all variants must satisfy
104 assert constraint maxGrossWeight {
105 chassis.curbWeight <= 3000[kg]
106 }
107 }
108
109 // ── Filtered feature views ───────────────────────────────
110 package PremiumFeatures {
111 import FeatureCatalog::**;
112 filter @FeatureTier and FeatureTier::tier == "premium";
113 }
114 package USFeatures {
115 import FeatureCatalog::**;
116 filter @MarketRegion and (MarketRegion::region == "US"
117 or MarketRegion::region == "ALL");
118 }
119 package EUFeatures {
120 import FeatureCatalog::**;
121 filter @MarketRegion and (MarketRegion::region == "EU"
122 or MarketRegion::region == "ALL");
123 }
124
125 // ── Fully resolved configurations ────────────────────────
126 part def SedanPetrolUS :> Vehicle {
127 part body redefines Vehicle::body = body::sedan;
128 part powertrain redefines Vehicle::powertrain = powertrain::petrol;
129 // Include US-market features from the filtered view
130 }
131
132 part def SUVElectricEU :> Vehicle {
133 part body redefines Vehicle::body = body::suv;
134 part powertrain redefines Vehicle::powertrain = powertrain::electric;
135 // Include EU-market features from the filtered view
136 }
137
138 part def TruckDieselUS :> Vehicle {
139 part body redefines Vehicle::body = body::truck;
140 part powertrain redefines Vehicle::powertrain = powertrain::diesel;
141
142 // Truck-specific constraint override
143 assert constraint towRating {
144 body.payloadCapacity >= 1500[kg]
145 }
146 }
147 }
该模型演示了:共享平台(底盘、制动、转向)、两个各含三个变体的变体点(车身形式、动力总成)、带市场区域与档次过滤表达式的元数据标记选装功能、适用于全部配置的平台级约束、变体特有约束(皮卡拖挂能力),以及面向不同细分市场的三个完整解析配置。
模块总结
| SysML v2 概念 | KerML 起源 | 关键规则 |
|---|---|---|
variation(作用于使用) | isVariation = true 的 Usage | 把某个特征标记为变体点;必须解析为恰好一个变体 |
variant | VariantMembership | 在变体点内声明一个允许的备选项 |
variation part def | isVariation = true 的 PartDefinition | 定义本身即是变体;其每次使用都继承变体语义 |
| 配置绑定 | BindingConnector | 通过 redefines 把变体使用解析到某个具体变体 |
| 部分配置 | 仍有部分变体未解析的特化 | 固定一部分选择,其余留待进一步特化 |
filter 表达式 | FilterExpression | 依据元数据条件从命名空间中挑选元素;产出一个视图 |
| 产品线包 | 内容混合的 Package | 三层模式:平台 + 可变性 + 配置 |
| 元数据标记 | 元数据注解 | 为元素标注区域、档次等筛选条件,供过滤使用 |