循序渐进 · 教学

本体设计最佳实践

这篇文章讲的是:如何把一个组织"建模"成一套人人(和 AI)都能看懂的数字结构。 下面用 10 个小步骤,把它拆开讲给完全没有基础的人听。

原文 Palantir Foundry · Ontology Best Practices 预计阅读 15 分钟 1 个互动练习 + 6 道测验
本文来源 · Source 内容整理自 Palantir Foundry 官方文档:
https://www.palantir.com/docs/foundry/ontology/ontology-best-practices/
原始标题:Ontology design: Best practices

一句话速览

本体设计最佳实践:这篇文章讲的是:如何把一个组织"建模"成一套人人(和 AI)都能看懂的数字结构。下面用 10 个小步骤,把它拆开讲给完全没有基础的人听。

1 本体(Ontology)到底是什么
假设一家医院有挂号系统、检验系统、设备系统、财务系统
2 一张 CSV 引发的思考
数据团队拿到一张订单 CSV,很自然地想:建一个叫 OrderData 的对象类型,一列对一个属性,完事
1

先搞清楚:本体(Ontology)到底是什么?

一句话:本体是你所在组织的"语义层",不是又一个数据库。

假设一家医院有挂号系统、检验系统、设备系统、财务系统。每个系统都有自己的表、自己的字段名、自己的主键。 人和人之间要沟通,得先做一轮"翻译":dtLastInspMod 到底是啥?pat_idpatient_no 是不是同一个东西?

本体(Ontology)就是在这些系统之上再建一层:不去描述"数据在哪个表里",而是描述 "现实世界里有什么东西、它们之间是什么关系"

打个比方:数据库是"仓库里的货架清单",本体是"这座城市的一张地图"。 地图不会告诉你数据存在哪个货架,但它会告诉你:这里有一家医院、一条路、一辆救护车,以及它们怎么连在一起。
The Ontology models the real world, not the source data. 本体建模的是现实世界,而不是源数据。

一个好的本体读起来应该是"顺"的——业务人员不用培训就能看懂,AI 智能体也能顺着它自己找答案。 判断标准很简单:如果看这张图的人需要反复问"这列是什么意思",那建模就失败了。

2

本体由五块积木拼成

先把名词认全,后面的原则才好理解。

Object type 对象类型
现实世界中的一类事物,不是一张表。比如 Patient(患者)、WorkOrder(工单)、Vessel(船舶)。
Property 属性
对象的特征。比如患者的姓名、出生日期。每个属性都应该讲得出用途,不是源表有什么就搬什么。
Link 链接
对象之间真实存在的关系:"这位患者去过这家医院"。注意:链接不是外键,外键是技术产物,链接是业务语义。
Action type 动作类型
人类或 AI 智能体做出的决策。比如"批准工单"。决策用 action,纯自动化的数据变换用 pipeline,别混用。
Interface 接口
一组"能力 / 角色"的抽象,可以被多个对象类型实现。比如 Inspectable(可被检查的)、Schedulable(可被预约的)。 接口是本体里避免造出一堆奇怪中间类型的关键工具——第 8 步会展开讲。
3

从一个反面例子讲起:一张 CSV 引发的思考

新手最常犯的错:把一张表原样搬成一个对象。

数据团队拿到一张订单 CSV,很自然地想:建一个叫 OrderData 的对象类型,一列对一个属性,完事。 这就是原文点名的反模式 「Kitchen Sink」(什么都往里塞)

下面这张表其实描述了 3 个现实实体。请你试试:点击「归属」列的按钮,把它分到正确的实体里。

CSV 列名示例值归属
order_idA-10023 订单 客户 产品
customer_name张三 订单 客户 产品
customer_emailzhang@x.com 订单 客户 产品
product_skuSKU-8812 订单 客户 产品
quantity3 订单 客户 产品
✗ 反模式:照抄表结构
OrderData - order_id - customer_name - customer_email - product_sku - quantity 一个类型照抄一张 CSV
✓ 推荐:建模领域
Order - order_id - quantity - 链接 → Customer、Product Customer - name - email Product - sku 三个类型,建模真实领域

为什么差别这么大?

问题后果
模型不直观人和 AI 都无法自然地在其中导航,因为结构和他们对业务的认知对不上。
与源头硬耦合源系统改一个字段,所有下游应用一起崩——因为本体在"镜像"源结构,而没有做抽象。
关系丢失被塞进列里的实体(比如订单上的 customer_name)无法被单独链接、搜索和推理。
难以复用被某一个系统形状塑造出来的对象类型,别的团队很难拿去用。
新手可执行的三步: ① 先别看数据,和业务专家一起列出"现实世界里有哪些东西"; ② 再设计对象模型; ③ 最后才把源数据映射进去。 顺序反了(先看数据再定模型)几乎是必错。
4

八条速查清单(先混个眼熟)

这是原文的实用检查表,后面四条核心原则会逐一解释其中几条。

1 · 建模现实,而非系统
对象类型代表真实实体,而不是某个源系统或某个部门的一种表达方式。
2 · 有意策划
每个属性都要有清晰的业务或技术价值,没有就别放。
3 · 跨团队协作
设计要有多个团队的利益相关者参与。孤岛团队是重复造轮子的主要来源。
4 · 保持对象类型专注
一个对象类型只代表一个独立实体。
5 · 选对工具
人或智能体的决策用 action types;自动化数据变换用 pipelines。
6 · 用接口做抽象
实体共享特征时用接口,别去造一个又宽又稀疏的对象类型。
7 · 记录你的决策
在 Ontology Manager 里为对象类型、属性、链接写清楚说明。
8 · 对照真实业务问题验证
跑一遍基于任务的分析演练,确认人和智能体能真的用它支撑决策。
5

四条核心原则

按优先级排序,冲突时高优先级胜出。

优先级原则一句话
1Domain-driven design 领域驱动设计建模现实世界,而不是源数据。
2Do not repeat yourself 不要重复自己同样的东西造了三次,就该重构了。
3Open for extension, closed for modification 开闭原则保护核心模型,让其他人能扩展它。
4Composition over deep hierarchies 组合优于深层继承用接口做多重继承,保持可插拔。
1

领域驱动设计

Domain-driven design · Model the real world, not the source data.

要避开什么

  • 对象类型在镜像源系统的数据表,而不是领域实体
  • 属性从源列 1:1 照搬,没有任何筛选
  • 命名沿用源系统习惯(dtLastInspMod),而不是业务语言(lastInspectionDate
  • 模型是"看着数据"设计出来的,而不是"理解了业务"设计出来的
  • 一行源数据里其实包含多个实体,却被建模成单个对象类型

该怎么做

  1. 先看领域,再看表结构和业务方一起定义"哪些概念重要"。一个数据集往往描述多个实体。
  2. 区分「身份」与「观测」如果一行数据表示对某实体的一次测量或事件,那实体和观测很可能是两个不同的对象类型。
  3. 为人命名API 名要直观、自解释。用 person.children 而不是 person.linkedChildPersonObjects
  4. 先建模,再映射数据理解领域 → 设计对象模型 → 把源数据映射进去。不要反过来。
  5. 非语义类型标记为 hidden纯技术用途的类型设为隐藏,保持默认视图干净,构建应用时仍可用。
2

不要重复自己(三法则)

Do not repeat yourself · If you built the same thing three times, refactor.

重复的对象类型、冗余的属性、复制粘贴的工作流,不仅是维护负担,更是上下文管理灾难—— 无论是人还是 AI 智能体,面对三个长得几乎一样的 Customer,都无法判断哪个才是"正主"。

一次是巧合,两次是信号,三次就该重构了。
✗ 三个团队各造一个
Sales Customer - name / email / phone Support Customer - name / email / phone Billing Customer - name / email / phone 三套类型 + 三套动作 = 三份维护负担
✓ 收敛成一个规范类型
Customer(唯一规范类型) - name / email / phone - salesStatus - supportTier - billingAccountId — 或者,若形态确实不同 — Interface: CustomerBase 由 SalesLead、SupportContact、 BillingAccount 实现

要避开什么

  • 多个对象类型拥有相同的属性和相似的链接
  • 同一段派生属性逻辑或动作逻辑散落在多个类型里
  • 不同团队为略有差异的用途造出近乎相同的对象类型
  • 存在只有细微差别、靠复制粘贴产生的工作流

该怎么做

  1. 做一次重复审计如果多个类型共享同一形态,评估:合并成一个类型 + 一个区分属性,还是共同实现一个接口。
  2. 收敛共享逻辑同一段派生属性或动作逻辑若能复用,抽成接口或共享函数。
  3. 统一团队私有副本合并为单一规范表示,用权限或过滤来满足各自诉求。
  4. 套用三法则一处重复可接受,两处是警告,三处就该动手重构。
3

对扩展开放,对修改关闭

Open for extension, closed for modification · Protect core models. Enable builders to extend them.

一个对象类型一旦上线、经过实战检验,它的核心结构就应该稳定下来。 别的团队要加新能力,应该是"在旁边加",而不是"进到里面改"。

✗ 直接改核心类型
Equipment - serialNumber - manufacturer - certificationAuthority(新) - certificationExpiry(新) - certificationStatus(新) - lastCertAudit(新) 四个新属性对大多数设备都是空的 现有消费者被迫跟着改
✓ 扩展而不修改
Equipment(原封不动) - serialNumber - manufacturer - 链接 → Equipment Certification Equipment Certification - certificationAuthority - certificationExpiry - certificationStatus Interface: Certifiable 核心类型不动,能力靠链接 + 接口加

要避开什么

  • 频繁对已确立的对象类型做破坏性改动,波及所有下游应用
  • 新需求靠改核心类型来满足,而不是扩展它
  • 团队为了满足自己的特殊需求去编辑共享接口或动作
  • 为某一团队做扩展时,安全边界意外扩大,影响到其他使用者

该怎么做

  1. 识别什么是本质确定哪些属性和链接真正属于这个实体的根本,把它们锁定。
  2. 为扩展而设计建核心类型时就预留空间:可链接的扩展类型、新的接口实现。
  3. 优先扩展而非修改新增内容先问一句:它该待在核心类型上,还是该放在扩展里(新链接类型 / 新接口实现 / 新属性命名空间)?
  4. 守住安全边界核心模型要有清晰的权限边界,确保扩展本体不会顺带扩大数据访问范围。
4

组合优于深层层次结构

Composition over deep hierarchies · Favor multiple inheritance via interfaces. Keep things pluggable.

Foundry 的本体支持通过接口实现多重继承。所以一个实体可以从多个"小而专"的抽象里各取所需, 而不必被塞进一条单一继承的链条里。

✗ 深层单继承
Asset └── PhysicalAsset └── Building └── SchedulableBuilding └── Arena 每出现一种新的能力组合 就要造一个新的中间类型。 再来个"可预约仓库"又要开新分支。
✓ 接口组合
Interface: Building - address - squareFootage Interface: SchedulableResource - schedulingCalendar - bookingPolicy Arena 同时实现两个接口 - arenaName / seatingCapacity 加"可预约仓库"只需再实现 同样两个接口,不动层次结构

要避开什么

  • 深长的单继承链,子类型存在的唯一目的就是拼凑父类能力
  • 出现 SchedulableBuildingInspectableVehicle 这类把两个无关概念硬揉在一起的"组合类型"
  • 工作流和具体对象类型紧耦合,明明可以面向共享接口来写
  • 给实体加一种新能力,就得重构整条继承链

该怎么做

  1. 围绕"能力 / 角色"设计接口小而专:InspectableSchedulableBillableDepreciable
  2. 用分类型接口做聚合比如 MilitaryAssetAircraftVesselGroundVehicle 实现,特别适合下钻式调查。
  3. 工作流面向接口编程建在 SchedulableResource 上的工作流,对体育馆、会议室、车辆全都适用,无需改动。
  4. 能组合就别继承实体需要多种能力时,实现多个接口,而不是往继承链深处插一层。
9

务实与权衡:这些是指南,不是法律

现实里有 deadline、有遗留系统、有平台能力限制——理想设计往往不能一步到位。

别做路障
如果时间很紧必须上线,就先做一个合理的版本,并留出明确的改进路径。
把代价说出口
推荐走捷径时,讲清楚放弃了什么、什么时候会出问题。比如:现在这个规模下反范式没问题,但超过 1 万个对象就该回来重看。
小步快跑,别大爆炸重构
一个"略有瑕疵但已经在用、已经在产生价值"的本体,胜过"理论上完美但还在设计中"的本体。
守住关键不变量
命名质量、语义清晰度、安全设计——这三样事后极难补救。可以在实现细节上偷工,别在这三样上偷工。
The Ontology is the software that powers your organization. 本体是驱动整个组织运转的软件。像对待生产代码库一样对待它,但把业务价值排在完美之上。

一页带走

如果只记四句话:

① 建模现实
先看业务,再看数据;命名说人话。
② 不要重复
第三次出现同样的东西,就重构。
③ 只加不改
核心模型锁住,新能力靠扩展。
④ 组合优先
多重能力用接口拼,别堆继承树。

最后别忘了验证:拿真实的业务问题去跑一遍,看人和 AI 智能体能不能顺着本体找到答案。 能找到,设计才算成立。

延伸阅读 · 相关页面

按主题横向跳转,不必顺着目录一篇篇读。

内容整理自 Palantir Foundry 官方文档 Ontology design: Best practices · 本页仅用于学习讲解,技术术语保留英文原文以便对照。

常见问题速答 · FAQ

关于「本体设计最佳实践」,读者最常问的几个问题。

本体(Ontology)到底是什么?
假设一家医院有挂号系统、检验系统、设备系统、财务系统。每个系统都有自己的表、自己的字段名、自己的主键。人和人之间要沟通,得先做一轮"翻译":dtLastInspMod 到底是啥?pat_id 和 patient_no 是不是同一个东西?
一张 CSV 引发的思考是什么?
数据团队拿到一张订单 CSV,很自然地想:建一个叫 OrderData 的对象类型,一列对一个属性,完事。这就是原文点名的反模式 「Kitchen Sink」(什么都往里塞)。