3. 模型规范体系的分层结构
模型规范不是一份“大而全”的文档,而是一套分层约束体系。不同层级回答不同问题:企业级回答“所有模型必须共同遵守什么”,项目级回答“这个项目在通用底线之上还要满足什么”,子系统级回答“这个模块内部如何组织”,命名与注释规范则贯穿三层,回答“人和工具如何读懂模型”。如果层级混乱,常见后果是:企业规范写得像操作手册,项目规范重复企业条款,子系统规范缺失导致接口随意,命名注释无人执行。
四层结构及其职责边界
企业级规范是强制底线,覆盖所有项目,通常包括:模型文件命名与目录结构、Simulink 版本与求解器基线、库链接与自定义库使用规则、模型配置参数(如 Solver、步长、诊断项)的默认值、安全与合规要求(如禁止使用某些模块、必须开启代码生成检查)。企业级规范应保持稳定,变更需评审,条款数量不宜过多,但每条必须可检查。
项目级规范在企业级之上增加项目特有约束。例如某电机控制项目要求:所有控制器模型必须采用定步长离散求解器,采样周期 1 ms;所有接口信号必须使用 Simulink.Signal 对象并指定数据类型;模型必须支持 MIL/SIL 两种测试模式。项目级规范通常由项目架构师或质量负责人维护,随项目阶段更新,但不得放宽企业级底线。
子系统级规范面向具体模块,规定内部结构、接口、状态机和数据管理方式。例如“电流环子系统”规范可要求:输入输出端口必须按 Ia_ref、Ib_ref、Ia_fb、Ib_fb 命名;内部禁止使用 Goto/From 跨层跳转;PI 控制器必须使用离散积分器并显式设置抗饱和;所有查表模块必须标注数据来源。子系统级规范最贴近实现,也最容易被忽视。
命名与注释规范是横向层,不单独构成一个“级别”,而是嵌入上述三层。命名规范应覆盖模型、子系统、信号、参数、总线、状态、事件等对象,给出可判定的规则,例如:信号名采用 小写字母+下划线,单位后缀用 _rpm、_A、_pu;禁止使用 Signal1、Out1 等默认名。注释规范要求每个子系统有用途说明,每个关键参数有来源和单位,每个状态机有状态转移条件说明。
规范文档的编写方法
编写规范文档时,先确定“可检查”原则:每条规范都应能回答“如何判断违反”。例如“信号命名应清晰”不可检查,应改为“信号名必须匹配正则 ^[a-z][a-z0-9_]*$,且不得以 _tmp 结尾”。再确定条款编号与层级归属,避免同一要求在三层重复。推荐结构为:适用范围、术语定义、条款正文、检查方式、例外申请流程、变更记录。
条款正文建议采用“规则 + 示例 + 反例”三件套。以项目级采样周期为例:规则为“控制器模型必须使用 1 ms 定步长离散求解器”;正例为 Solver: Fixed-step, Fixed-step size: 0.001;反例为 Solver: Variable-step。这样评审时可直接对照,减少歧义。
落地方法:从文档到门禁
规范落地不能只靠宣讲。可执行路径是:模板化——提供符合规范的模型模板与库,新建模型默认合规;检查脚本——用 MATLAB/Simulink Check、Model Advisor 或自定义脚本把可自动检查的条款变成检查项;评审门禁——在 Pull Request 或模型入库前运行检查,未通过不允许合并;度量反馈——统计违规类型与数量,反向优化规范;版本化——规范文档与检查脚本同版本管理,避免“文档说 A、脚本查 B”。
一个可参考的检查清单示例
| 层级 | 检查项 | 判定方式 | 示例 |
|---|---|---|---|
| 企业级 | 求解器类型 | 自动 | 必须为 Fixed-step |
| 企业级 | 禁止模块 | 自动 | 不得使用 Interpreted MATLAB Function |
| 项目级 | 采样周期 | 自动 | 控制器模型固定步长 0.001 s |
| 项目级 | 接口信号对象 | 自动 | 所有输入输出必须绑定 Simulink.Signal |
| 子系统级 | 端口命名 | 自动 | 匹配 ^[a-z][a-z0-9_]*$ |
| 子系统级 | 状态机注释 | 人工 | 每个状态必须有转移条件说明 |
| 命名注释 | 默认名禁用 | 自动 | 不得出现 Signal1、Out1 |
| 命名注释 | 单位后缀 | 自动 | 物理量信号必须带单位后缀 |
最后需要强调:分层结构的目的不是增加文档数量,而是让每条约束都有明确归属和检查方式。企业级守住底线,项目级适配场景,子系统级保证实现质量,命名与注释让模型可读可维护。四者配合,规范才能从“纸面要求”变成“模型质量的实际控制手段”。