UML与CIM:电力行业标准建模实战指南

发布时间:2026/9/8 11:24:25
UML与CIM:电力行业标准建模实战指南 之前的电力信息化项目里最让人头疼的往往不是并发量、不是部署链路而是数据模型对不齐。调度侧叫“开关”计量侧叫“电表”GIS侧叫“节点”研发团队写代码时各自建模联调阶段全靠临时对翻译表。这种问题通常不是某一个团队的责任而是行业标准没有在系统设计阶段被统一表达出来。要解决它UML统一建模语言Unified Modeling Language是很关键的沟通工具。这篇继续“用UML表示的行业标准”系列的第二篇聚焦电力和智能电网领域从CIM这类行业模型切入把UML的类图、用例图、序列图、状态图、包图如何落地到电网业务中讲清楚。如果你是刚接触电网信息化的新手可以在这里建立基本的领域认知如果你已经在做能源系统、SCADA、电力营销或配电自动化项目本文提供的建模思路、完整代码示例和排错清单可以直接复用到你的项目设计文档中。1. 背景与核心概念1.1 为什么电力行业标准必须依赖UML电力系统是一个覆盖发、输、变、配、用、调多个环节的复杂系统任何一次设备状态的变更都可能沿着电气拓扑传播影响一大片区域。要支撑这样的系统稳定运行单纯靠企业内部的私有数据格式远不够用跨系统、跨厂商、跨调度机构的数据交互必须建立在共同的语义基础上。这就像不同国家的人要用一套统一的手势来描述同一件事否则彼此无法理解。而在电力行业这套“手势”就是行业标准。早期电力自动化系统大量使用点表、规约和私有数据库表来交换数据调度端、变电站端、配网端各说各话。后来行业逐渐认识到必须先定义一套公共信息模型把现实世界的电力设备、拓扑、量测、资产、作业抽象成可被计算机处理的对象再基于这些对象进行接口设计。UML正好是用来描述这种对象模型的标准语言它允许标准制定者用统一的图形和语义表达类、属性、关联、继承和约束。UML之所以成为行业标准的表达工具是因为它具备几个明显的优势。第一它是一种图形化语言能直观呈现对象之间的关系第二它有严格的元模型规范不同建模工具之间可以通过XMI等格式交换模型第三它能够支撑模型驱动的开发方式从UML类图可以生成Java、C、数据库表结构等实现产物。正因如此IEC国际电工委员会等组织在定义电力行业标准时普遍采用UML来描述领域模型。1.2 什么是CIM公共信息模型在电力行业标准中CIMCommon Information Model公共信息模型是一个绕不开的基础概念。CIM最初服务于能量管理系统EMS的应用程序接口也就是IEC 61970标准。它使用面向对象的方式把电力系统中的主要对象——变电站、线路、变压器、开关、量测、发电机组、负荷等——抽象成类并定义这些对象之间的关联、继承和聚合关系。后来电力行业发现CIM这套建模思路不仅可以用于调度自动化也可以推广到配电管理、电力市场、输电网规划、新能源接入等更广泛的场景。因此IEC 61968在配电管理系统接口中延续并扩展了CIM形成了覆盖更多业务域的公共模型。今天我们看到的各种电网信息化系统无论是设备台账、拓扑分析、状态估计还是停电管理、客户服务底层几乎都可以追溯到CIM中的某个类或某个关联。CIM的典型特征是把“设备”和“量测”分开建模。设备描述的是物理存在比如一台断路器、一段交流线段量测描述的是设备在运行中产生的数据比如有功功率、无功功率、电压幅值。这种分离使得同一个设备模型可以承载不同业务系统的数据。与之类似CIM还把“资产”和“设备”做了区分资产是拥有物理身份的对象比如某台变压器的出厂序列号与铭牌信息设备则是运行在网络模型中的对象。这种建模思路与UML的类、继承、聚合概念完全对应。1.3 UML在标准落地中的桥梁作用很多同学阅读IEC标准原文时会发现标准文档里大量出现类图、包图和对象模型片段这些图往往被直接用作标准正文的一部分。原因在于文字描述存在歧义图形化表达更精确UML正是标准制定者选定的“共同语言”。从标准到系统落地通常要经历这样几个阶段标准制定者先用UML定义领域模型建模人员将UML模型转换为数据库表结构或代码骨架系统架构师基于这些模型设计服务接口开发人员实现具体业务功能。在这个过程中UML模型既是标准文档的组成部分又是设计实现的基础起到连接业务概念和IT系统的桥梁作用。如果说IFC标准在建筑信息模型BIM领域起到了统一数据描述的作用那么CIM在电网领域扮演的角色与之类似只不过领域从建筑换成了电力。理解了这层关系再看调度系统、配电主站系统、资产管理系统中那些以“IdentifiedObject”为基类的对象就不会觉得陌生了。2. UML核心图型在电网建模中的作用UML提供多种类型的图无论是标准制定还是项目设计都不是所有图都会用到。在电力和智能电网领域最常用的是类图、用例图、序列图、状态图和包图下面逐一展开。2.1 类图描述电网静态结构类图是电网建模中使用频率最高的一种UML图CIM标准的主体内容基本由类图构成。类图描述的是对象的类型、属性以及对象之间的关系。CIM中定义了一个叫IdentifiedObject的基类几乎所有CIM对象都继承自它这个基类包含mRID、name、description等公共属性承担了唯一标识和命名描述的作用。以它为根向下派生出PowerSystemResource电力系统资源、Equipment设备、Substation变电站、Line线路等具体类。类图中另外一类重要关系是聚合和组合。例如一个Substation由多个Bay间隔组成一个Bay又包含多个Equipment这种整体与部分的约束在CIM中被描述得非常清楚。若脱离类图仅靠数据库外键去推断包含关系很容易产生歧义。绘制电网类图时建议把继承关系放在垂直方向把关联关系放在水平方向。同一个包内的类尽量聚合展示不同包之间的类可以通过带导航方向的关联线表达。这样设计的类图不仅结构清晰也方便后续转换为代码或数据库结构。2.2 用例图描述业务功能边界用例图并不描述数据模型而是从用户视角描述系统提供哪些功能、参与者和系统边界在哪里。在电力信息化项目中用例图常用于描述调度员、运行人员、检修人员与系统的交互边界。一个典型的智能电网用例图可以包括以下用例SCADA数据采集、断路器远程分合、负荷预测、停电研判、检修工单下发、告警推送等。参与者包括调度员、配电运维人员、监控系统、外部气象系统等。绘制用例图时要注意粒度控制。如果系统规模较大建议按业务域拆分先画顶层用例图再对每个用例进行细化。不要把所有交互都塞进一张图否则会失去表达力。很多学生作业或初版设计文档之所以被评审质疑就是因为用例图的边界和粒度没有控制好。2.3 序列图描述交互流程序列图展示的是多个对象之间按时间顺序传递消息的过程。在电力业务中很典型的场景是一个遥控操作流程调度员发出遥控预令主站系统校验权限和拓扑向远方终端下发控制命令终端执行后反馈响应主站确认并归档。这类流程如果用文字描述往往需要大段说明但读者对“谁先谁后”的理解仍然容易产生偏差。序列图通过生命线和消息箭头把执行顺序直观展示出来对系统联调和接口设计非常有帮助。一图胜千言序列图在电力标准原语验证、接口联调和故障溯源时发挥的作用有时候比类图更直接因为它直接回答“系统之间如何协作”的问题。2.4 状态图描述设备生命周期电力设备是有生命周期状态的。一台断路器可能处于运行、检修、故障、备用、退役等状态一个检修工单可能经历草稿、审批、执行、完工、归档等状态。状态图能够清晰地表达这些状态以及触发状态迁移的事件。状态图的价值在于找出“是否所有状态迁移都被允许”的漏洞。例如一台断路器从“运行”直接跳转到“退役”中间是否允许是否需要先经过“检修”状态这些业务规则通过状态迁移条件标识出来比靠开发人员阅读几百行代码来判断要直观得多。2.5 包图组织复杂模型CIM模型涉及大量类如果全部平铺在一张图中即便是几十页的图纸也放不下。UML中的包图Package Diagram用于组织模型元素它可以把一组相关的类放在同一个包中并描述包与包之间的依赖关系。CIM标准中将模型拆分为Core、Topology、Wires、Meas、Generation、LoadModel、SCADA等若干包。Core包定义了公共基类和最通用的对象Topology包描述拓扑连接关系Wires包描述输电和配电网络中的导电设备Meas包描述量测数据模型。包图的存在让阅读者可以按业务域逐层深入而不必一开始就淹没在庞大的类关系网络中。3. 环境准备与建模工具选型3.1 主流UML建模工具对比UML建模工具种类很多从重量级企业工具到轻量级文本化工具各有适用场景。下面用表格做一个横向对比方便你按照项目需要选择。工具类型适合场景学习成本备注Enterprise Architect桌面客户端大型CIM模型、企业级标准建模较高支持XMI导入导出电力行业广泛使用PapyrusEclipse插件学术与开源建模中高基于Eclipse支持UML2.x规范StarUML桌面客户端中小型项目快速建模低操作直观插件丰富PlantUML文本化工具代码化建模、文档嵌入低文本即可生成图适合Git管理draw.io在线绘图原型图、临时草图低不支持复杂标准建模如果你在参与正式的电力行业标准建模或企业级架构治理Enterprise Architect是更接近工程界的选项因为它对XMI、CIM Profile以及模型库的支持比较完善。不过这类工具价格不低学习曲线也陡。对于学习UML、做课程作业或验证模型思路StarUML和PlantUML完全够用。个人建议在团队协作场景中优先考虑PlantUML这类文本化建模方式。原因很简单文本文件可以纳入Git版本管理代码评审时可以看到模型变更的diff生成的图片可以嵌入Wiki、CSDN博客和接口文档这一点在多人协作和知识沉淀上优势非常明显。3.2 PlantUML环境准备PlantUML是本文实战环节使用的工具它是一个用文本描述UML图的工具。只要有一段简单的描述语法就能生成对应的UML图。环境准备并不复杂。PlantUML本体由Java编写所以系统需要安装Java运行环境JRE建议使用Java 8或更高版本。接着下载plantuml.jar或者使用VSCode中的PlantUML插件自动管理依赖。为了生成部分复杂的图型还需要安装Graphviz建议一并安装。如果你习惯在VSCode中工作可以安装PlantUML插件并在settings.json中配置plantuml.jar的路径这样在编辑器中按快捷键即可预览和导出图片。对于只是偶尔绘制类图的同学也可以直接使用在线PlantUML服务器在浏览器中粘贴语法生成图片。版本方面无需过度纠结。不同版本的PlantUML对大多数类图语法的支持是一致的本文示例采用通用语法可直接在常用版本中运行。4. 完整实战用UML表达CIM核心模型4.1 建模目标与范围这一节我们以一个完整的示例串联UML类图、包图和代码实现。假设现在需要为某个电网信息化项目中“变电站设备台账模块”建立领域模型。要求如下变电站拥有间隔。间隔包含多种设备。设备包括断路器、交流线段、电力变压器。设备之间通过端子连接形成拓扑关系。设备可挂接量测数据。这个建模目标看似简单实际涉及CIM中至少三个核心包Core包设备与基类、Topology包端子与连接节点、Meas包量测。4.2 定义顶层包结构在PlantUML中包用package关键字表示。我们首先创建三个包Core、Topology、Meas。包的命名与CIM保持一致便于后续对照标准扩展。包图不是必须单独绘制可以先在类图中用package组织类再通过依赖线说明包与包之间的依赖关系。这里需要注意CIM的包结构非常庞大建模时不宜追求一次画全。先圈定最小范围画清楚核心类后面再根据业务扩展包和类这样模型的可读性和可维护性都会好很多。4.3 建立核心基类在CIM中几乎所有对象都继承自IdentifiedObject。它定义了三个关键属性mRID全局唯一标识字符串类型。name对象名称允许重复。description对象描述。从IdentifiedObject直接派生PowerSystemResource和Equipment。前者表示电力系统资源是一个较宏观的资源概念后者表示实际一次设备。虽然两者在业务上存在联系但它们在CIM中分别承担不同的建模责任。创建基类可以避免每个设备类重复定义标识和名称属性这样在后续编写Java类或建表时只需要处理一次公共字段。4.4 表达设备继承关系在类图中继承关系用空心三角形实线表示。在PlantUML中通过|--符号实现继承。我们要表达EquipmentContainer设备容器继承自PowerSystemResourceSubstation和Bay继承自EquipmentContainerBreaker、ACLineSegment、PowerTransformer继承自Equipment。这段继承关系是CIM设备模型的骨架。将通用属性放在基类中子类只扩展自己的特有属性这种设计直接降低了模型复杂度也让数据库表和代码结构保持对称。4.5 表达变电站拓扑关系拓扑关系的核心是端子Terminal和连接节点ConnectivityNode。在CIM中Terminal是设备与拓扑网络之间的连接点。一个ConnectivityNode可以连接多个端子通过这些端子不同设备才在电气上连接起来。Substation组合多个BayBay组合多个EquipmentEquipment组合多个Terminal。这样设计的直接好处是原本复杂的电网拓扑被拆解为设备、端子、连接节点三层结构任何一次拓扑变更只要修改端子与连接节点的关联不需要大范围调整设备类本身。4.6 表达量测数据模型量测数据在CIM中归入Meas包。最简单的做法是定义Measurement基类并派生Analog模拟量如有功功率和Discrete离散量如开关位置。一个PowerSystemResource可以关联多个Measurement一个Measurement也可以被多个资源使用。为控制示例复杂度这里只做简单的一对多关联。实际CIM中对量测的建模要细致得多还会区分量测类型、量测单位、数据质量等属性。为了便于理解我们在Measurement上定义measurementType、unitSymbol两个属性分别表示量测类型和单位符号。4.7 完整PlantUML模型代码下面是完整的PlantUML代码演示了上述CIM核心模型的类图。复制到编辑器或在线服务器即可直接渲染。startuml CIM Core Model Sample package Core { class IdentifiedObject { mRID : string name : string description : string } class PowerSystemResource { location : string } class Equipment { normallyInService : boolean inService : boolean } class EquipmentContainer { } } package Topology { class Terminal { sequenceNumber : integer } class ConnectivityNode { description : string } } package Wires { class Substation { region : string } class Bay { bayType : string } class Breaker { ratedCurrent : float open : boolean } class ACLineSegment { length : float r : float x : float } class PowerTransformer { ratedPower : float windingType : string } } package Meas { class Measurement { measurementType : string unitSymbol : string } class Analog { positiveFlowIn : boolean } class Discrete { value : integer } } IdentifiedObject |-- PowerSystemResource IdentifiedObject |-- Equipment IdentifiedObject |-- EquipmentContainer IdentifiedObject |-- Measurement PowerSystemResource |-- EquipmentContainer EquipmentContainer |-- Substation EquipmentContainer |-- Bay PowerSystemResource |-- Equipment Equipment |-- Breaker Equipment |-- ACLineSegment Equipment |-- PowerTransformer Equipment *-- Terminal Bay *-- Equipment Terminal 1 -- 0..* ConnectivityNode : connects PowerSystemResource 1 o-- 0..* Measurement : has Measurement |-- Analog Measurement |-- Discrete note top of IdentifiedObject : CIM中几乎所有对象的基类 note bottom of ConnectivityNode : 拓扑连接的核心节点 enduml这段代码中package用于划分包结构class定义类|--表示继承*--表示组合o--表示聚合--表示关联并可以附带重数限制。渲染后可以看到清晰的类关系图。4.8 运行与验证在VSCode中打开PlantUML插件后将上述代码保存为cim-core.puml使用快捷键AltD即可预览渲染效果。如果是在命令行环境中也可以使用以下命令java -jar plantuml.jar -tpng cim-core.puml执行成功后会在同目录下生成cim-core.png图片。此时可以检查三个方面继承关系是否正确连接到基类。组合与聚合的实心/空心菱形是否区分正确。关联线上的重数是否是期望的语义。例如Bay与Equipment之间用实心菱形表示组合关系代表间隔与设备同生共死的强依赖而PowerSystemResource与Measurement之间用空心菱形表示聚合关系代表设备可以单独存在量测数据可以后续补充或移除。5. 从UML模型到代码落地5.1 类图与数据库表结构映射UML类图刻画的是对象模型落到关系数据库时需要转换为表结构。转换规则并不复杂通常一个类对应一张表类属性变成表的字段类之间的一对多关联通过外键实现多对多关联需要额外的中间表。以IdentifiedObject基类为例可以建立一张公共表存储对象的通用属性。但实际项目中更常见的做法是每张业务表直接包含mrid、name、description字段避免跨表的类继承映射过于复杂。子类表额外增加自己特有的字段并通过主键关联到基类表。这里给出一个简化的SQL建表示例CREATE TABLE identified_object ( mrid VARCHAR(64) PRIMARY KEY, name VARCHAR(255), description VARCHAR(512) ); CREATE TABLE substation ( mrid VARCHAR(64) PRIMARY KEY, name VARCHAR(255), description VARCHAR(512), region VARCHAR(128), FOREIGN KEY (mrid) REFERENCES identified_object(mrid) ); CREATE TABLE bay ( mrid VARCHAR(64) PRIMARY KEY, name VARCHAR(255), description VARCHAR(512), substation_mrid VARCHAR(64), FOREIGN KEY (substation_mrid) REFERENCES substation(mrid) ); CREATE TABLE terminal ( mrid VARCHAR(64) PRIMARY KEY, sequence_number INTEGER, equipment_mrid VARCHAR(64), connectivity_node_mrid VARCHAR(64), FOREIGN KEY (equipment_mrid) REFERENCES identified_object(mrid), FOREIGN KEY (connectivity_node_mrid) REFERENCES connectivity_node(mrid) );需要注意的是UML继承关系映射到关系数据库时有“每类一表”、“每个具体类一表”和“单表继承”三种常见策略。具体选择哪种取决于查询性能、字段冗余度和团队习惯。电力和智能电网行业的数据量通常较大频繁的跨表关联查询会影响性能因此很多实际系统反而倾向采用“单表继承”策略在一个宽表里同时保存多个子类字段但这也带来字段冗长和约束难以保证的缺点。设计时需要权衡。5.2 类图与Java代码映射如果用Java实现CIM模型UML类图中的类、继承和关联可以比较自然地映射为Java接口、抽象类和普通类。以IdentifiedObject和Breaker为例Java代码可以写成public abstract class IdentifiedObject { protected String mRID; protected String name; protected String description; } public abstract class PowerSystemResource extends IdentifiedObject { protected String location; } public abstract class Equipment extends PowerSystemResource { protected boolean normallyInService; protected boolean inService; } public class Breaker extends Equipment { private float ratedCurrent; private boolean open; }在这种设计下公共属性集中在基类中子类通过继承获得公共属性只是额外加入自己特有的业务字段。如果模型后续发生变化比如新增一种设备类型只需要新增一个子类不需要改动已有类降低了模块间的耦合度。5.3 模型变更管理电网项目往往持续多年CIM模型也会随业务扩张持续演进。模型变更管理是整个信息化建设中容易被忽视的环节。一个常见的教训是标准文档中的类图已经升级到新版本但系统中数据库表结构和代码对象模型还停留在旧版本导致接口切版时大面积报错。建议将UML模型文件纳入版本管理并设定模型评审流程。每次变更需要同时更新模型文件、数据库脚本、接口文档和代码骨架。如果团队规模较大可以在CI流水线中加入模型lint检查确保模型文件没有语法错误包依赖没有循环引用类与类之间的关系符合既定约束。把模型当作代码一样管理才能在长期演进中保持模型的可维护性。6. 常见问题与排查思路UML建模本身并不难但初学者在实际操作中经常会遇到一些问题。下面把高频问题整理成一张排查表。问题现象常见原因解决思路PlantUML中文乱码文件编码不是UTF-8统一使用UTF-8保存文件避免在Windows记事本中另存为ANSI编码类图线条重叠严重类太多布局太密将大图拆分为多个包图或使用together命令控制类间距继承方向画反混淆子类和父类方向记住空心三角形永远指向父类组合与聚合混淆对生命周期依赖理解不足组合关系下整体删除时部分必须删除聚合关系下部分可独立存在模型无法用工具导出XMI工具版本或插件不兼容使用统一版本建模工具导出前检查UML配置文件标准模型与系统代码不一致模型变更未同步到代码建立模型评审流程将模型变更与代码提交关联数据库中找不到继承表未映射基类字段在子表显式补充mrid、name等公共字段或使用单表继承策略在这些问题中组合与聚合的混淆最普遍。简单判断标准是如果整体消失后部分没有存在意义则使用组合比如Bay与Equipment之间就是组合关系间隔删除后其中的设备如果不同时迁移到其他间隔就失去了归属如果部分可以独立存在则使用聚合比如设备与量测之间设备删除后量测记录从业务上应当保留用于审计。7. 最佳实践与工程建议7.1 以标准原文为基础不要闭门造车在电力和智能电网领域UML建模不是凭空发挥而是对行业标准的解释和落地。动手建模前先找到对应的标准章节尽量理解标准原文对类、属性的定义。CIM中类的命名和属性定义极其严谨例如设备在运行中是否可用、是否投产这些状态位在标准中都有明确含义。自行创造一套近义命名会给后续集成带来不可估量的沟通成本。7.2 统一命名规范与语义建模文件建议统一使用英文命名因为标准原文与大多数工具链对英文支持更好。name字段可以用于中文显示名称description可以承载更详细的业务解释。类名采用大驼峰风格属性名采用小驼峰风格布尔类型属性统一使用is或has前缀尽量避免中英文混用。7.3 控制模型粒度拆分绘制一张类图塞下几十个类最终往往谁也看不清。建议一个业务域或一个子系统单独绘制类图在包图中体现整体结构关系。对于复杂标准模型可以按照包的维度拆分例如Core包、Topology包、Meas包各画一张类图阅读者按需查阅。7.4 模型评审与团队协作UML模型是标准落地的“地图”如果只有架构师一个人看得懂团队协作效率就上不来。建议每次模型更新后做一次全员可见的评审重点检查继承、聚合、组合、关联重数是否符合业务语义。使用PlantUML文本化建模可以把模型变更的diff展示得清清楚楚这一点在很多团队实践中非常有效。将UML图嵌入CSDN博客或内部知识库也可以帮助后来者快速理解领域概念。7.5 生产环境变更注意安全边界如果UML模型最终映射到数据库变更或生产接口调整必须格外谨慎。涉及生产环境的数据模型变更要先在测试环境验证做好备份按照最小权限原则操作。UML模型本身的修改是设计层面的事可以放开讨论但从模型到生产库表结构、接口实现的变更要按照变更管理流程执行避免因为“图改了一笔代码没跟上”导致线上事故。8. 下一步学习建议掌握UML与CIM核心模型的用法之后可以沿着以下方向继续深入。先精读IEC 61970和IEC 61968标准中关于CIM的公开介绍部分重点关注Core、Topology、Wires、Meas四个包的类图和关联。不必追求逐字理解先把握模型设计的整体思路。接着用本文的PlantUML代码做基础尝试扩展一个类例如增加“电容柜”或“光伏逆变器”并补充对应的数据库建表语句和Java类体会模型变更对代码和库表的影响。之后可以研究UML中更复杂的关系语义包括依赖、实现、关联类、组合与聚合的边界场景。如果是在校学生正在准备UML系统设计相关的期末大作业也可以参考本文的建模思路选择一个具体的电网业务场景比如“配网停电研判”或“新能源并网监控”用UML设计一套包含用例图、类图、序列图和状态图的完整方案。先画清楚业务边界再定义核心对象和交互流程然后补充数据模型与代码映射这样的作业完成度会非常扎实。电力与智能电网的信息化体系庞大UML是进入这个领域的一把钥匙。把模型画清楚把标准理解透后续无论是做接口开发、数据中台还是数字孪生都能少走很多弯路。建议先收藏本文动手把这份CIM核心模型跑出来再逐步扩展成属于你自己的电力业务模型。