ELEC5620 Week 11 特化建模语言:Profile 与 OCL 讲课总结

ELEC5620 Week 11 讲课总结:Specialise a Modeling Language

课程:ELEC5620 — Model Based Software Engineering,Semester 2 2026 讲师:Dong Yuan 来源:讲义 PDF 11 Specialise a Modeling Langurage.pdf(38 页,文件名原样)+ ELEC5620-TUT-11.pdf(21 页,PDF 内封面写作 “Tutorial 10”,内容是元建模与 Profile 的回顾)。本周文件夹没有 Lab Note。本周无转录稿。

本周覆盖(软件建模路线的最后一步): 1. 为什么要特化 UML;Profile 机制 2. Stereotype、Tag definition、Extension;信号量与 AI Agent 例子 3. Overlay Profile 4. OCL:上下文、不变式、集合、量词、前后置条件 5. HealthcareAgent Profile 完整例子 6. Agentic DSL 前沿研究

相关笔记:Week 10 元建模|Week 03 需求建模(agentic use case)


一、背景:为什么要特化建模语言

1.1 从方法大战到 UML

1990 年代:Booch OOD、OMT(Object Modelling Technique)、HOOD、Shlaer-Mellor、OODLE、CRC/RDD……还有约 80 种其他方法。UML 统一了它们,但一种通用语言不可能直接满足所有领域 → 需要特化。

1.2 两种特化路线(结合 Week 10 四层架构)

路线 做法 位置 代价
重量级:新建元模型 用 MOF 从头定义一个新的 M2 语言(DSL) 与 UML 平级的 M2 工具、经验都要重建
轻量级:UML Profile 在 UML 元模型上扩展(不修改) 挂在 UML(M2)上 与标准 UML 兼容,可复用 UML 工具和经验

UML 自带语言特化工具包:Profile 机制。 它允许对 UML 模型做领域特定的解释,同时与通用(标准)UML 兼容。由此派生出 UML for Real Time、UML for Systems Engineering、UML for Business Modeling 等。

1.3 SysML 与 MARTE

Profile 领域 说明
SysML 系统工程 提供捕获需求及其与其他系统工程制品关系的概念和关系(如 requirement 图);是 use case 建模的补充(Friedenthal, Moore, Steiner; OMG)
MARTE 实时与嵌入式应用 时间、资源、性能建模

二、UML Profile

2.1 定义

Profile:为特定领域和平台定制 UML 模型的通用扩展机制。 Profile 由 stereotypes(构造型)、tag definitions(标签定义)和 constraints(约束) 定义。

两种用途:

用途 含义
定义领域特定建模语言(DSML) 用构造型给 UML 元素加上领域含义,形成新的“方言”
定义可叠加到现有模型上的领域特定视点 重新解释原有模型的一种方式(Overlay,见第三节)

2.2 Stereotype(构造型)

  • 让设计者扩展 UML 的词汇表,从现有元素派生出新的模型元素
  • 具有适合特定问题域的特定属性
  • 构造型的属性称为 tag definitions(标签定义);应用构造型时给这些属性赋的值叫 tagged values

2.3 例子:给 UML 加一个 Semaphore 概念

信号量语义:一种限制多线程环境中并发访问数量的特殊对象。达到上限时,后续访问被挂起,直到某个线程释放信号量,此时最早被挂起的访问获得访问权。

需要的是一种特殊的对象:拥有 UML 对象的所有一般特性,但加上精化。

设计选择:精化 UML 的 Class 概念——

  1. “附加”信号量语义(通过给 Class 加构造型来隐含)
  2. 添加约束捕获信号量语义(如达到最大并发数后,后续请求按 FIFO 排队)
  3. 添加特征属性(如并发上限 limit)
  4. 添加特征操作(getSemaphore()、releaseSemaphore())

本质:创建原元类的一个新“子类”,带上上述精化。

图形定义:

┌──────────────────┐
│ «metaclass» │
│ UML::Class │
└────────▲─────────┘
┃ Extension(实线 + 实心三角箭头,从构造型指向元类)
┌──────────────────────────┐ ┌─────────────────────────────┐
│ «stereotype» [可选图标] │ ┄┄┄┄┄ │ {active->size() <= limit} │
│ Semaphore │ │ {limit <= MAXlimit} │
│ limit : Integer │ └─────────────────────────────┘
│ getSema : Operation │ Constraints
│ relSema : Operation │
└──────────────────────────┘

2.4 Extension vs Generalization(记号易混)

关系 连接 记号 例子
Extension 构造型 → 元类 实线 + 实心(黑)三角箭头 «stereotype» Tool ━━▶ «metaclass» UML::Operation
Generalization 构造型 → 构造型 实线 + 空心三角箭头 «stereotype» ReviewedTool ──▷ «stereotype» Tool

讲义注:构造型的特化只是为了解释记号(可选)。考试画 profile 图时,构造型到元类必须用 Extension(实心箭头),不要画成普通泛化。

2.5 例子:AI Agent 构造型

«metaclass» UML::Class
▲ (Extension)
«stereotype» Agent
AIModel : LLM
context : String
genPlan : Planer
startConv : ConvController
约束:{ active->size() <= limit <= MAX }

用法:在类图里把某个类标为 «Agent»,就能给它填 AIModel、context 等标签值,工具也能据此做检查或生成代码。


三、Overlay Profile(叠加 Profile)

  • Profile 可作为叠加机制,动态地 apply / unapply,提供 UML 模型的某种视图
  • 让 UML 模型从视点定义者的角度被解释
  • ⚠️ apply 或 unapply profile 对底层模型没有影响

例:把 UML 模型片段重新解释为排队网络,做性能分析:

原模型:           user1 ──▶ DBase ◀── user2
apply 性能 profile:«client» user1 {arrivalRate = …}
«server» DBase {serviceRate = …}
«client» user2 {arrivalRate = …}
unapply: 回到原模型,什么都没变

叠加后可以用排队论计算,例如对单服务器 M/M/1 队列:

其中 是 arrivalRate, 是 serviceRate。(公式为标准排队论补充,讲义只给出 apply/unapply 示意。)

与 Week 2 的 Model Transformation(“UML → 排队网络模型”的域到域转换)呼应;与 Week 4 的视点呼应——叠加 profile 就是一种视点。


四、OCL:Object Constraint Language

4.1 为什么类图需要约束

  • UML 作为一种非正式语言,声明了属性和关系,但需要对它们的值加上精确规则
  • OCL 是 UML 语境下表达关于模型的精确规则的形式语言;补充 UML 图,描述有效对象和操作必须满足的条件
  • OMG 标准化,用于为 UML 分类器和对象写约束和查询

例:Adult (+parent 0..*) —— (+child 0..*) Child,多重性写得太宽松,用 OCL 收紧:

context Child inv:
self.parent->size() <= 2

4.2 讲义贯穿的 Person 类

Person
+name : String
+isMarried : Boolean
+gender : Gender
+age : Integer
+isSenior() : Boolean
自关联:husband 0..1 —— wife 0..1;friend 0..* —— 0..*

4.3 上下文与不变式

  • Context:约束(也叫不变式 invariant)所作用的类(或对象)——context Person inv: ...
  • 类约束是从上下文类的一个匿名成员的视角写的(即 self)⇒ 对类的所有成员都成立
context Person inv:
((self.isMarried) and (self.gender = #M))
implies ((self.wife->size() = 1) and (self.husband->size() = 0))

读法:已婚男性恰好有一个 wife,没有 husband。

4.4 访问属性:点号

self.name        -- 返回 name 字符串
self.isSenior() -- 返回 True / False
self.friend -- 返回一个集合:self 的所有朋友

4.5 数据类型与运算符

类别 内容
基本类型 复用 UML:Boolean、Integer、String、Real;支持常见算术和逻辑运算
集合类型 Set、OrderedSet、Bag、Sequence(都是 Collection 的子类型)
模型类型 建模者定义的应用类,如 Person、Adult、Child、Gender

数值:<、>、<=、>=、+、-、*、/、.mod()…… 逻辑:not、or、and、xor、=、<>(不等)、implies、if … then … else … endif

4.6 集合操作与 -> 记号(重点)

对集合应用操作用右箭头 ->;访问对象属性用点 .。

操作 含义
size() 集合大小
count(v) v 出现的次数
includes(v) 是否包含 v
includesAll(c) 是否包含集合 c 的全部元素
isEmpty() / notEmpty() 是否为空 / 非空
exists(expr) 至少一个元素使 expr 为真
forAll(expr) 所有元素使 expr 为真
self.friend->size()      -- self 的朋友数
self.friend->isEmpty() -- self 是否没有朋友

4.7 量词

OCL 一阶逻辑 例子
exists self.friend->exists(f : Person \| f.name = 'Bob') —— 至少一个朋友叫 Bob
forAll Person.allInstances()->forAll(p : Person \| p.name <> '') —— 任何人的名字都不能是空串

4.8 前置条件、后置条件(Design by Contract)

  • 适用于 Operations、Receptions 和 UML Behaviors
  • pre:操作前必须成立;post:操作完成后必须成立
  • 后置条件中可用 attribute@pre 引用操作执行前的值

4.9 定义操作

context <operation-name>(<parameters>) : <return-type>
[pre: <Boolean-expr>]
[post: <Boolean-expr>]
[body: <expression>] -- 必须求值为 <return-type> 的一种

context Person::isSenior() : Boolean
pre: age >= 0
post: age = age@pre -- 操作完成后 age 不变
body: (age >= 65)

4.10 OCL 练习(基于 Person 类,自拟用于复习)

自然语言规则 OCL
年龄非负 context Person inv: self.age >= 0
不能是自己的朋友 context Person inv: not self.friend->includes(self)
已婚者必须至少有一个配偶 context Person inv: self.isMarried implies (self.wife->size() + self.husband->size() = 1)
未成年人不能结婚 context Person inv: self.age < 18 implies not self.isMarried
所有朋友都已成年 context Person inv: self.friend->forAll(f \| f.age >= 18)
marry(p) 之后双方都已婚 context Person::marry(p : Person) pre: not self.isMarried and not p.isMarried post: self.isMarried and p.isMarried
birthday() 让年龄加 1 context Person::birthday() post: self.age = self.age@pre + 1

常见错误:对集合用 .(应用 ->);在 inv 里忘了 context;implies 前后颠倒;后置条件里该用 @pre 的地方没用。


五、完整例子:HealthcareAgent Profile

5.1 场景

  • 目标:安排一次已批准的随访预约
  • 允许的工作:查看转诊详情、提议预约
  • Agent 架构(三个组件):
«component» Decision «component» Controller «component» Service
提议下一步,使用观察结果 maxSteps、允许的操作 授权调用、检查审批

这就是 Week 4 的控制与功能分离:Decision(LLM 推理,功能)只“提议”;Controller 持有控制策略;Service 在执行点检查审批(机制)。

5.2 工作流与需求

阶段 做什么
Read referral 检查当前授权和同意
Propose booking 呈现确切的动作供审批
Commit booking 检查审批、身份和时段
Complete or stop 记录结果、超时或预算耗尽

需求到模型属性的对应:

需求 建模为
Goal and maxSteps 步数计数器和停止决策
Audit and timeout 记录的结果和时间界限
Purpose and consent policy 当前同意和访问范围

5.3 需要建模什么

方案 A:定义一种建模语言(Week 10 的路线)

  • 抽象语法:Agent 拥有 Tool,使用 DataSource
  • 具体语法:与 UML 相同
  • 语义:Agent 通过调用工具协调预约,并在执行时检查审批……

方案 B:定义基于 UML Profile 的 DSML(本周路线)

  • UML 元模型(Class、Operation)定义 UML 概念
  • Stereotype 为 UML 元素定义领域含义
  • Extension 指出允许扩展的 UML 元类
  • 类型化属性(tag definitions)在构造型应用上保存值

5.4 Profile 定义

«profile» HealthcareAgent
┌─────────────────────┐ ┌────────────────────────┐ ┌─────────────────────┐
│ «metaclass» │ │ «metaclass» │ │ «metaclass» │
│ UML::Class │ │ UML::Operation │ │ UML::Class │
└─────────▲───────────┘ └──────────▲─────────────┘ └─────────▲───────────┘
┃ Extension ┃ Extension ┃ Extension
┌─────────────────────┐ ┌────────────────────────┐ ┌─────────────────────┐
│ «stereotype» Agent │ │ «stereotype» Tool │ │ «stereotype» │
│ goal : String │ │ effect : Effect │ │ DataSource │
│ autonomy : Autonomy │ │ approvalRequired : Bool│ │ resource : String │
│ maxSteps : Integer │ │ auditRequired : Bool │ │ purpose : String │
│ │ │ timeoutSec : Integer │ │ consentRequired:Bool│
└─────────────────────┘ └────────────────────────┘ └─────────────────────┘

标签定义的取值:

标签 取值
Autonomy(枚举) assist、supervised、bounded
Effect(枚举) 对领域服务数据的 read 或 write
maxSteps 最多提议的工具调用次数,包括失败的调用

注意 Tool 扩展的是 UML::Operation(工具是 agent 能调用的操作),而 Agent 和 DataSource 扩展 UML::Class。

5.5 OCL 约束(讲义原文)

context HealthcareAgent::Agent
inv GoalPresent: self.goal.size() > 0
inv StepBound: self.maxSteps >= 1 and self.maxSteps <= 20

context HealthcareAgent::Tool
inv WriteNeedsApproval: self.effect = HealthcareAgent::Effect::write
implies self.approvalRequired
inv AuditRequired: self.auditRequired
inv PositiveTimeout: self.timeoutSec > 0

context HealthcareAgent::DataSource
inv PurposePresent: self.purpose.size() > 0
inv ConsentRequired: self.consentRequired

逐条解读:

约束 对应需求
GoalPresent 每个 agent 必须有明确目标(Week 3:写业务结果)
StepBound 步数有上界(1–20),防止无限循环、烧 token
WriteNeedsApproval 有写效果的工具必须需要审批——Week 3 “高影响动作要人工检查点”、Week 5 “High-impact action? → add approval + policy” 的形式化版本
AuditRequired 所有工具调用都要审计(可重建动作原因,Week 4 auditability)
PositiveTimeout 每个工具有超时
PurposePresent / ConsentRequired 数据源必须说明用途并要求同意(隐私)

注意 goal.size() 这里用的是点号——因为 goal 是 String,size() 是 String 的操作,不是集合操作。对比 self.friend->size()(集合用 ->)。

应用示例(M1 模型中):

«Agent» FollowUpBookingAgent {goal = "Arrange approved follow-up", autonomy = bounded, maxSteps = 8}
«Tool» readReferral() {effect = read, approvalRequired = false, auditRequired = true, timeoutSec = 10}
«Tool» commitBooking() {effect = write, approvalRequired = true, auditRequired = true, timeoutSec = 30}
«DataSource» ReferralStore {resource = "EHR referrals", purpose = "follow-up scheduling", consentRequired = true}

如果有人把 commitBooking 的 approvalRequired 改成 false,WriteNeedsApproval 会在建模工具中直接报错——这就是“模型是 agent 控制平面”的意义。


六、Agentic 软件 DSL 的最新进展

论文 要点
Malamas et al., “Toward efficient vibe coding: An LLM-based agent for low-code software development”, Journal of Computer Languages (2025) DSL 给领域提供显式的概念、关系和规则;模型用这套词汇描述应用,而不是无限制的程序文本。低代码平台提供建模工具,但用户仍需选择、连接元素并满足语言约束。LLM 帮助用户在基于 DSL 的低代码平台中构建模型——用户描述想要的功能,不必先学会所有建模命令
Delgado, Burgueño, Clarisó, “A framework for assessing the capabilities of code generation of constraint DSLs with LLMs”, JSS (2026) 提出评估 LLM 从文本规格生成 DSL 代码(OCL)的框架,并与 Python 比较;区分良构性(well-formedness)与正确性——语法有效的代码仍可能表达错误的约束;代码修复和多次生成能提升结果,但 Python 整体表现更好
Wang, Poskitt, Sun, “AgentSpec: Customizable runtime enforcement for safe and reliable LLM agents”, ICSE 2026 提出一种 DSL,用于规定并在运行时强制执行 LLM agent 的行为限制;规则 = trigger(何时适用)+ predicate(检查条件)+ enforcement(违反时如何响应);在代码执行、具身 agent、自动驾驶场景中评估;显著减少不安全动作,运行时开销为毫秒级

另外:新的会议 ACM Conference on AI and Agentic Systems (CAIS)——复合 AI 架构、优化和部署的严谨、可复现研究。

与 Week 10/11 的联系:AgentSpec 的 trigger–predicate–enforcement 本质上就是一个运行时检查的约束语言,可以看作把本周 OCL 约束(WriteNeedsApproval)从设计时搬到了运行时。第二篇论文提醒:让 LLM 写 OCL 时,语法对 ≠ 语义对,必须验证。


七、Tutorial 11 要点

ELEC5620-TUT-11.pdf(封面写 Tutorial 10)是 Week 10 元建模 + Week 11 Profile 的回顾,没有新增题目,内容包括:

  • 元建模语言、MOF、元模型定义、OMG 四层架构、UML 规格三部分、UML 元模型片段、模型与图的关系、语义(静态/动态,四种定义方法)、命名空间元模型 —— 详见 Week 10
  • 特化 UML、SysML、Profile 定义与两种用途、Stereotype、Overlay Profile —— 即本文第一至三节

复习用的综合题(自拟):为“智能理财 agent”(Week 7 的例子)设计一个 Profile。

解答思路: 1. 识别领域概念:Advisor agent(Class)、Trade 工具(Operation)、MarketFeed 数据源(Class) 2. 选择被扩展的元类:«Agent» → UML::Class、«TradeTool» → UML::Operation、«MarketFeed» → UML::Class 3. 定义标签:«TradeTool» { maxAmount : Real, effect : Effect, approvalRequired : Boolean }、«Agent» { riskProfile : RiskLevel, maxSteps : Integer } 4. 写 OCL:context TradeTool inv: self.effect = Effect::write implies self.approvalRequired;context TradeTool inv: self.maxAmount > 0;context Agent inv: self.riskProfile = RiskLevel::low implies self.maxSteps <= 10 5. 用 Extension(实心箭头)画构造型到元类,构造型之间如需特化用空心箭头


八、本周考点速记 / 易错点

  1. 特化 UML 的两条路:新建元模型(重量级 DSL)vs Profile(轻量级,与 UML 兼容,复用工具)。
  2. Profile = stereotypes + tag definitions + constraints;两种用途:定义 DSML 和叠加领域视点。
  3. Stereotype 扩展 UML 词汇,从现有元素派生;其属性叫 tag definitions。
  4. Extension(实心三角,构造型→元类)vs Generalization(空心三角,构造型→构造型)。
  5. Semaphore 例子四步:附加语义、加约束(FIFO)、加属性(limit)、加操作(get/release)。
  6. Overlay profile:可 apply/unapply,不影响底层模型;例:排队网络性能分析。
  7. SysML(系统工程,需求建模补充 use case)、MARTE(实时嵌入式)。
  8. OCL:context X inv:;self;. 访问属性,-> 集合操作;Set/OrderedSet/Bag/Sequence;exists ∃、forAll ∀;implies;allInstances()。
  9. 前后置条件:pre:、post:、body:、@pre 取旧值。
  10. HealthcareAgent Profile:«Agent»(goal、autonomy、maxSteps)、«Tool»(扩展 Operation;effect、approvalRequired、auditRequired、timeoutSec)、«DataSource»(resource、purpose、consentRequired);关键约束 WriteNeedsApproval。
  11. 前沿:LLM + DSL 低代码;LLM 生成 OCL 要区分良构 vs 正确;AgentSpec = trigger + predicate + enforcement 的运行时约束 DSL。
  12. 易错:把 Extension 画成普通泛化;集合操作用点号;以为 unapply profile 会删除模型信息;Tool 扩展的元类写成 Class。