4. 包图与模型组织
当模型从几十个元素增长到几百甚至上千个元素时,真正决定项目能否持续维护的,往往不是单个类或状态机画得多精细,而是模型有没有被组织成清晰、可导航、可复用的结构。包(Package)就是 Cameo Systems Modeler 中承担这一职责的核心容器:它既是命名空间,又是依赖与导入关系的载体,也是团队分工和模型库复用的基本单位。
包的本质:命名空间 + 容器 + 依赖端点
在 SysML/UML 语义中,包首先是一个 Namespace(命名空间)。包内元素的全限定名由外层包名逐级拼接而成,例如 Vehicle::Powertrain::Engine 表示 Engine 位于 Powertrain 包内,而 Powertrain 又位于 Vehicle 包内。这意味着两个不同包中可以存在同名元素,只要它们的全限定名不同就不会冲突。包同时是容器,通过 containment(包含)关系持有其内部元素;包还是依赖关系的端点,Import、Merge、Access 等关系都发生在包与包之间。
理解这一点非常关键:包图不是“画几个文件夹”,而是在表达命名空间层级、可见性规则和依赖方向。一个组织良好的包结构,能让模型使用者在不了解全部细节的情况下,仅凭包名和依赖箭头就判断出“谁能看到谁、改动会影响谁”。
包图的绘制要点
在 Cameo 中新建包图(Package Diagram)后,从 Containment 树拖入包元素即可。包的标准符号是左上角带小标签页的矩形,包名写在矩形内部;包之间的依赖用虚线箭头表示,箭头从依赖方指向被依赖方。常见的几种关系需要区分清楚:
- Containment(包含):用带十字圆圈的实线或嵌套画法表示,表示“物理上放在里面”,是结构层级。
- «import»:公有导入,被导入包的公有元素在本包中可直接以简单名引用,且会传递到本包的子包。
- «access»:私有导入,被导入元素只在本包内可见,不向子包传递。
- «merge»:包合并,把目标包的内容合并进源包,常用于把通用库合并进项目专用包。
绘制时建议遵循“一屏一主题”原则:一张包图只表达一个层级的组织关系,不要把所有子包和所有依赖都塞进同一张图。对于大型模型,可以按视图分层——顶层画系统级包划分,第二层画各领域包内部结构,第三层才画具体元素。
包导入与合并:可见性规则决定引用方式
导入和合并是包图最容易混淆的部分,需要从“可见性”和“内容复制”两个角度区分。
«import» 与 «access» 属于引用式导入。它们不复制元素,只是在源包中建立一条指向目标包的可见性通道。使用 «import» 时,目标包的公有元素在源包及其所有子包中都可以用简单名引用;使用 «access» 时,只有源包自身能引用,子包必须重新导入。例如,若 Vehicle::Powertrain 用 «import» 导入了 CommonLibrary,那么 Vehicle::Powertrain::Engine 可以直接写 PhysicalQuantity;若改用 «access»,则 Engine 必须写全限定名或由 Powertrain 再次显式导入。
«merge» 属于内容合并式关系。包合并会把目标包(被合并包)中的元素“并入”源包,源包中同名元素会与目标包元素合并,不同名元素则被添加进来。它常用于把通用库合并进项目专用包,使项目包获得库中全部定义,同时允许在项目包中覆盖或扩展特定元素。需要注意的是,合并是双向语义的:源包中被合并进来的元素与目标包保持同一性,修改目标包会影响所有合并它的包,因此合并关系应谨慎使用,避免形成难以追踪的隐式耦合。
模型命名空间管理
命名空间管理的核心目标是:让全限定名稳定、可预测,避免重名冲突和循环依赖。在 Cameo 中可以通过以下方式落实:
- 统一命名规范:包名使用大驼峰(如
Powertrain),元素名使用业务语义(如EngineController),避免使用Package1、Block_2这类自动生成名。 - 控制层级深度:一般建议 3~5 层,过深会导致全限定名冗长、引用困难;过浅则无法隔离不同领域。
- 避免循环导入:若 A 导入 B、B 又导入 A,会造成命名空间解析歧义。可用依赖矩阵或 Cameo 的 Dependency Matrix 检查。
- 使用 Root 包隔离项目:每个项目建立独立 Root 包,通用库放在共享 Root 下,通过导入引用,避免直接修改库内容。
当出现同名元素时,Cameo 会在引用处提示歧义,此时应使用全限定名或调整导入范围来消除冲突,而不是简单重命名破坏已有引用。
模型库与复用策略
模型库的价值在于把经过验证的类型、接口、单位、枚举等沉淀为可复用资产。一个可落地的复用策略通常包含三层:
| 层级 | 内容 | 复用方式 |
|---|---|---|
| 基础库 | 单位、值类型、基础枚举、通用接口 | «import» 到各项目包 |
| 领域库 | 某领域通用块、端口类型、约束 | «import» 或 «merge» 到领域包 |
| 项目包 | 项目专用块、参数、具体实例 | 引用基础库与领域库,本地扩展 |
复用时的关键判断是:被复用元素是否稳定。若基础库中的 PhysicalQuantity 被 20 个项目引用,一旦修改其属性,所有项目都会受影响。因此基础库应经过评审并版本化,项目包通过导入引用而非复制粘贴来使用它。对于需要本地定制的场景,可在项目包中创建继承自库元素的子类型,而不是直接修改库元素。
综合来看,包图与模型组织不是建模完成后的“整理工作”,而是贯穿建模始终的结构决策。先规划命名空间层级,再明确导入与合并关系,最后把稳定内容沉淀为库,模型才能从一次性交付物变成可持续演进的资产。