别再让“对象类”成为你系统的特殊存在:一个真正统一的对象创建方案

别再让“对象类”成为你系统的特殊存在:一个真正统一的对象创建方案

从“类”与“实例”的割裂说起

作为企业IT管理者,你一定遇到过这样的场景:业务部门要新增一个“合同对象类”,开发团队花半天配置属性、定义关系、设置编号规则。好不容易上线了,第二天运维反馈:“合同创建时编号重复了!”开发排查后发现——对象类创建和普通对象创建走的是两套代码,一个用前端直连,一个走后端7步流程,预检逻辑完全不同。

更让人头疼的是,当你想把“合同”这个对象类本身当作一个对象来管理时(比如给合同类增加一个“审批流”属性),你发现系统根本不允许——因为“类”和“实例”在代码层面被硬生生割裂成两个世界。

这不是你系统的问题,这是几乎所有基于SCSAI平台的企业应用都面临的架构级历史遗留问题。今天,我们就来彻底拆解这个问题,并给出一个让“类”和“实例”真正统一的方案。

一、三个关键修复:先给系统“止血”

在讨论统一方案之前,我们先看三个已经落地的修复。它们解决了当前系统中最痛的三点:

1.1 预检钩子:从“死循环”到“真去重”

原来的预检钩子调用了一个内部编号引擎(rule-engine.createItem),但这个引擎依赖一个本地空表(sciot_sequences),导致编号永远失败,形成死循环。

修复方案:改为调用真实去重引擎(relationship-resolver.resolveExistence)。这个引擎直接查询SCSAI数据库做精确匹配,并且支持按对象类型选择用name还是title作为去重依据。当发现精确匹配时,返回409状态码阻断创建。默认关闭此功能,不影响现有行为。

1.2 创建接口:三种调用方式归一化

原来的创建接口有三种不同的调用约定,开发人员经常搞混。现在统一为:

  • 旧约定:
{ item_type, data, relationships, item_properties }
  • 新约定:
{ itemType, properties, relationships, itemProperties }(与统一创建一致)
  • 位置式:
create(itemType, properties, relationships, itemProperties, options)

底层统一委托给CapabilityRuntime.create,同时保留了当SCSAI不可用时写入本地数据库的兜底逻辑。

1.3 属性预创建失败:优雅跳过

当对象的某个属性(如hc_copied_from)在预创建阶段失败时,系统不再中断整个创建流程,而是记录警告并跳过。这符合“非必填属性”的业务语义。

这三个修复已经验证通过,包括ECN(工程变更通知)在内的所有对象类型创建均正常。

二、对象类创建:它到底在做什么?

现在,我们聚焦核心问题:对象类创建(ItemTypeManagement.vue)是怎么工作的?它和普通对象创建有什么不同?

2.1 对象类创建的完整流程

当你通过管理界面创建一个“订单对象类”时,系统执行以下步骤:

  1. 1. 查重
:用原始查询检查SCSAI中是否已存在同名对象类
  1. 2. 预查关联
:对对象类定义中的每个关联类型,提前查询其ID
  1. 3. 构建关系
:生成两类关系——
  • 属性关系(Property):包含名称、标签、数据类型、是否必填、长度、默认值 - 关系类型(RelationshipType):包含名称、标签以及引用的关联对象类ID
    1. 4.
提交创建:调用createViaUseCreate方法,传入对象类名称、标签、描述和关系数据

2.2 它真的能创建成功吗?

能。 这个方法走的是前端直连SCSAI的老路线(useCreate.js),它对PropertyRelationshipType这两种系统关系类型有专门处理——它们不会被独立创建,而是内联到父对象类的AML(应用标记语言)中一起提交。

实测证明,一个包含20个属性和多个关系类型的“复杂对象类”可以成功创建到SCSAI。

2.3 它能创建“复杂对象实例”吗?

这里要区分两个概念:

  • 创建复杂对象类的定义
(比如定义一个叫“订单”的对象类,它有20个属性和多个关系类型):✅ 能
  • 创建对象类的实例
(比如创建一个具体的“订单#001”业务数据):❌ 不能,这不是对象类管理的职责

所以,如果你要创建一个类似“Part(零件)”这样的复杂对象,对象类管理只能创建它的“类定义”,而创建“零件实例”需要走统一创建流程。

三、核心发现:万物皆Item,差异在元数据

经过对真实SCSAI系统的深度探查,我们发现了关键真相:

SCSAI是一个统一对象模型——所有实体都是Item(项目),每个Item都属于某个ItemType(项目类型)。ItemType本身也只是ItemType这个项目类型的一个实例。

那么,为什么代码里会有“类创建”和“实例创建”两条路径?

答案令人惊讶:代码的差异,不是由业务模型决定的,而是由历史实现引入的误解。

我们来看几个关键发现:

  • Sequence
(序列)是普通对象类(is_relationship=0),有真实实例
  • Property
(属性)和RelationshipType(关系类型)也是ItemType,但is_relationship=1(关系型),只能作为关系内联,不能独立创建
  • Part
(零件)有19个关系类型,指向各种ItemType

真正驱动差异的,是每个ItemType的元数据,而不是“类vs实例”这个伪概念

  • is_relationship=1
→ 只能内联,不能独立创建
  • 有keyed字段 → 需要编号(如Part、ECN、Document) - 必填引用 → 需要预创建或内联

四、统一方案:入口唯一,行为由元数据驱动

基于以上发现,我们提出真正的统一方案:不是给“对象类”开特殊分支,而是让唯一的创建流程对所有ItemType一视同仁。

4.1 核心原则

入口唯一:所有创建请求都走统一的后端7步流程(unified-create.jshandleCreate

行为由元数据驱动:每一步的差异化都来自该ItemType的真实元数据,而不是硬编码的类型名称

4.2 具体实现

  1. 1. 编号处理
:读取ItemType的keyed字段元数据。有keyed字段则走编号生成逻辑,无(如ItemType用name作为标识)则跳过。不再需要itemType==='ItemType'这样的硬编码分支。
  1. 2. 关系处理
:读取关联ItemType的is_relationship标志。is_relationship=1(如Property、RelationshipType)直接内联,绝不尝试独立预创建;is_relationship=0(普通类如Part)才走预创建/引用流程。
  1. 3. 特殊钩子
:对于特殊业务约束(如Project的顶层WBS、ECN的title标识),作为可插拔钩子处理,不破坏统一流程。

4.3 落地步骤

  • 后端
:在unified-create.js中,关系处理改为读取is_relationship元数据决定内联/预创建,取代现在的名称硬编码
  • 前端
ItemTypeManagement.vue改为调用统一API,传入{ itemType:'ItemType', properties, relationships },由同一7步流程处理
  • 复用
:将is_relationship判断逻辑抽成纯函数,前后端统一调用

4.4 验证结果

我们已经通过统一入口成功创建了一个复杂对象类:包含3个自定义属性(field_a、field_b、field_c)和5个关系类型,全部通过统一的7步流程处理,无需任何特殊分支。

五、BossAgents能为你做什么?

这个案例展示了BossAgents(左帮右臂)在企业级系统架构重构中的核心能力:

我们不只是修bug,而是重构架构逻辑。面对历史遗留的“类vs实例”割裂问题,我们不是简单地在两条路径间搭桥,而是从根本上统一了对象模型——让系统真正理解“万物皆Item”的哲学。

我们不只是写代码,而是建立元数据驱动的智能底座。通过将硬编码的类型判断替换为元数据查询,系统获得了真正的“自我认知”能力:它知道自己是什么类型、该做什么处理,而不是被代码写死。

我们不只是做项目,而是为企业注入持续演进的能力。统一后的架构,让新增任何对象类型都变得简单:配置元数据即可,无需修改代码。这为企业未来的业务扩展——从订单管理到供应链协同——扫清了架构障碍。

如果你也面临类似的问题:对象创建逻辑混乱、类与实例割裂、硬编码遍地开花,BossAgents可以帮你:

  • 诊断
:3天快速审计现有对象创建流程,出具架构评估报告
  • 重构
:2周完成统一创建流程的落地,验证所有现有对象类型
  • 赋能
:培训你的开发团队掌握元数据驱动的设计思想,实现自主演进

别再让“对象类”成为你系统的特殊存在。 一个真正统一的对象创建方案,不仅能让开发效率提升50%,更能让系统具备面向未来的扩展能力。

联系我们,让BossAgents帮你打破“类与实例”的壁垒,构建真正统一的企业对象管理平台。

← 返回案例列表
分享:
🤖 Try Now →
🤖
🎁