第3章:系统建模语言SysML:SysML基础、用例图与活动图建模车门开关场景、需求图与模块定义图的应用
3.1 为什么地铁车门系统需要SysML?
说实话,我刚开始做车门系统时,用的还是Word文档加Visio流程图。那时候项目小,几个人凑一起就能把逻辑理清楚。但后来项目越来越大,一个车门控制器要跟TCMS、PIS、障碍物检测、站台屏蔽门联动……光靠自然语言描述,根本说不清楚。
举个例子,你写一句「车门在收到开门指令后打开」,这句话在不同人眼里可能完全不一样。是收到指令立刻开?还是先解锁再开?解锁失败怎么办?这些细节,文字描述很难覆盖全。
SysML就是来解决这个问题的。它是一种系统建模语言,专门用来描述复杂系统的结构、行为、需求和约束。说白了,就是让团队里每个人看到的「车门开关」是同一个东西。
核心观点:SysML不是编程语言,它是「画图的语言」。但它的图不是随便画的,每一条线、每一个框都有严格的语义。我见过不少团队把SysML图当成Visio来画,结果图是漂亮了,但根本没法做仿真和验证。
3.2 SysML基础:九种图,三种视角
SysML一共定义了九种图,但别被吓到。实际做车门系统,常用的就四五种。我习惯把它们分成三类视角:
| 视角 | 包含的图 | 在车门系统中的作用 |
|---|---|---|
| 行为视角 | 用例图、活动图、序列图、状态机图 | 描述车门怎么动、谁触发、顺序如何 |
| 结构视角 | 模块定义图、内部块图、包图 | 描述车门有哪些部件、怎么连接 |
| 需求视角 | 需求图、参数图 | 描述车门必须满足什么指标 |
嗯,这里要注意:很多人一上来就画活动图,画得热火朝天,结果需求没理清楚,结构也没定义。我的建议是——先画用例图,把「谁要干什么」搞清楚,再往下走。
3.3 用例图:谁在跟车门打交道?
用例图是SysML里最简单的图,但也是最容易被低估的。它回答三个问题:
- 系统边界在哪?(车门系统包括什么,不包括什么)
- 谁在使用系统?(司机、乘客、维护人员、TCMS)
- 他们想干什么?(开门、关门、紧急解锁、防夹检测)
我在做某条地铁线的车门系统时,一开始用例图画得太粗,把「乘客」也当成一个actor。后来发现不对——乘客并不直接操作车门,他只是「被服务」的对象。真正的actor应该是司机、ATC系统、站台屏蔽门系统。这个区分很重要,因为它决定了你的接口设计。
个人经验:画用例图时,我习惯用「动词+名词」的格式命名用例。比如「打开车门」、「紧急解锁」、「检测障碍物」。不要用「车门控制」这种模糊的名字,太笼统了,没法往下分解。
3.4 活动图:车门开关的「流程图Plus」
活动图是SysML里我最常用的图之一。它跟传统的流程图很像,但多了几个好东西:
- 泳道(Partition):可以区分不同角色负责的活动。比如司机发指令、车门控制器执行、电机响应。
- 对象节点(Object Node):可以表示活动之间传递的数据。比如「开门指令」这个信号。
- 控制节点:分支、合并、分叉、汇合,用来表达并行和选择。
咱们来看一个车门开关的典型活动图场景:
活动:正常开门流程
[司机] 按下开门按钮
→ 发送开门指令(对象节点:开门指令)
→ [车门控制器] 接收指令
→ 判断当前状态(是否在站台、速度是否为0)
→ 分支:
├─ 条件满足 → 执行解锁
├─ 条件不满足 → 返回错误状态
→ 解锁成功后,发送电机正转指令
→ [电机] 执行开门动作
→ 检测门位置传感器
→ 到达全开位置 → 发送「门已开」信号
你看,这样画出来,谁在什么时候做什么,清清楚楚。我曾经在一个项目里,用活动图帮团队发现了两个隐藏问题:一是「解锁」和「开门」之间缺少超时保护,二是「门已开」信号没有反馈给TCMS。这些问题如果在编码阶段才发现,改起来就麻烦了。
避坑指南:活动图不要画得太细。我曾经见过有人把电机每个PWM周期都画成一个活动节点,那图根本没法看。活动图的粒度应该控制在「一个活动可以由一个人或一个子系统独立完成」这个级别。太细了用状态机图,太粗了用用例图。
3.5 需求图:把「人话」变成「机器能懂的约束」
需求图是SysML里最有价值但也最容易被忽略的图。为什么?因为很多人觉得需求就是写文档,画图多此一举。
但我的经验是——需求图最大的好处是「可追溯」。你可以把一条需求跟一个用例、一个模块、一个测试用例关联起来。这样当需求变更时,你能立刻知道哪些地方要改。
举个例子,车门系统有一条需求:
需求ID: REQ-DOOR-001
需求文本: 车门应在收到开门指令后3秒内完成开门动作
类型: 性能需求
来源: 用户需求规格书
关联用例: UC-001 正常开门
关联模块: 车门控制器、电机驱动模块
验证方法: 测试用例TC-001
你看,一条需求不再是孤零零的一句话。它跟谁有关、怎么验证、谁负责,一目了然。我在做某项目时,客户突然要求把开门时间从3秒改成2.5秒。我打开需求图一看,直接定位到电机驱动模块和测试用例,半天就改完了。要是没有这个追溯关系,估计得翻三天文档。
3.6 模块定义图:车门系统的「乐高说明书」
模块定义图(BDD)用来定义系统的静态结构。说白了,就是告诉你车门系统由哪些模块组成,模块之间是什么关系。
常见的模块关系有三种:
- 组合(Composition):整体与部分的关系,部分不能脱离整体存在。比如车门总成包含门板、电机、传感器。
- 聚合(Aggregation):整体与部分的关系,但部分可以独立存在。比如车队包含多辆车,车可以独立存在。
- 泛化(Generalization):父子关系,子类继承父类的特性。比如「紧急解锁按钮」是「按钮」的一种。
我习惯在BDD里把每个模块的属性和操作也标出来。比如:
模块:车门控制器
属性:
- 当前状态: 枚举(锁定, 解锁, 开门中, 关门中, 故障)
- 开门超时时间: 整数 (单位: 毫秒)
操作:
+ 接收指令(指令类型)
+ 执行解锁()
+ 执行开门()
+ 检测故障()
这样画出来,开发人员拿到BDD就知道要定义哪些变量、实现哪些函数。硬件工程师也知道要预留哪些接口。说白了,BDD就是团队沟通的「共同语言」。
我的习惯:BDD和活动图要配合着看。BDD告诉你「有什么」,活动图告诉你「怎么动」。我一般先画BDD把模块定下来,再画活动图描述模块之间的交互。两个图来回迭代几次,系统架构就清晰了。
3.7 小结:SysML不是画图,是思考
说了这么多,其实我想表达一个观点:SysML的价值不在于图本身,而在于画图过程中逼你去思考的那些问题。
- 用例图逼你思考:边界在哪?谁在用?
- 活动图逼你思考:顺序对吗?异常怎么处理?
- 需求图逼你思考:需求可验证吗?跟谁相关?
- BDD逼你思考:模块划分合理吗?接口清晰吗?
我见过太多团队,SysML图画得漂漂亮亮,但项目该出问题还是出问题。为什么?因为图是「画」出来的,不是「想」出来的。真正的好图,每一根线背后都有决策依据。
下一章,咱们聊聊怎么用SysML做车门系统的需求分析。到时候我会拿一个真实项目的案例来拆解,看看需求是怎么从「一句话」变成「可执行的模型」的。