Files
Structive/docs/DESIGN.zh-CN.md
T
2026-08-08 21:21:23 +08:00

11 KiB
Raw Blame History

Structive 设计理念与原则

English

1. 设计目标

Structive 的目标是在保留 C++ 原生对象模型的前提下,为普通 struct 增加显式结构语义。

它不是第二套语言、反射运行时、安全边界、ORM 或对象框架。它是一层尽可能贴近普通 C++ 的结构元数据和 managed property 能力。

目标模型:

普通 C++ 数据
    + 显式 Schema
    + Property 固有能力
    + Metadata
    + 可选 Managed Synchronization
    + 可选 Runtime Adapter

2. 第一原则:增强,而不是替代

第一原则:

增强 struct,而不是替代 struct。

注册字段仍是真实 C++ 成员。未注册状态仍然是普通 C++。只要 C++ 类型本身允许,raw access 永远存在。

Structive 不要求每个字段变成 Property<T>,也不应该迫使业务对象进入第二套对象模型。

原则

如果一个能力可以通过 metadata 或很薄的 managed layer 实现,就不要改变原生 member model。

3. 类型信息与实例行为必须分层

Structive 有两层架构。

3.1 类型层

Type_Descriptor<T>Object_Schema 保存结构事实:

  • 注册 Property
  • key
  • intrinsic readable/writable
  • Attribute
  • Constraint
  • 默认 synchronization 描述。

这些属于类型。

3.2 实例层

Property_Object<T> 提供实例行为:

  • managed read/write
  • 可写同步域所需的锁存储;
  • 多属性 Guard
  • traversal
  • type-erased runtime access
  • 可选的每实例 synchronization override。

原则

除非信息真的随实例变化,否则不要把类型级事实复制到每个对象里。

4. 注册必须显式

Structive 不假设所有成员都是 Property。

struct Device : Property_Object<Device> {
    int temperature;
    int internal_cache;
};

只注册 temperature 时,internal_cache 完全不属于 Structive Schema。

原则

注册决定参与;不在 Schema 中就不属于 Structive。

5. Intrinsic Capability 属于 Property 自己

Structive 没有内建访问控制系统

Property 只描述自己固有支持什么:

none
read
write
read_write

通常由 Accessor 自动推导,也可以通过 metadata 显式收窄。

field<&Device::serial_number>(key<"serial_number">, read_only)

它表达:

在 Structive managed model 中,这个属性可读、不可写。

它不表达哪个用户、服务、GUI 或进程有权限看到它。

原则

Property capability 描述结构,不描述授权。

6. Core 不拥有外部访问策略

Structive 不定义下面这些 managed access mode

internal
external
persistence
role
context
permission

GUI 自己决定哪些属性可编辑,RPC 自己决定暴露哪些字段,持久化系统自己决定保存哪些字段。

Core 只提供结构事实,Consumer 自己定义策略。

原则

不要因为某个 Adapter 需要策略,就把这个策略塞进 Core。

7. Raw Access 与 Managed Access 是两种契约

下面两句故意具有不同语义:

device.temperature = 30;
device.write<&Device::temperature>(30);

Raw path 遵守普通 C++。Managed path 遵守 Structive Schema 与同步模型。

如果代码直接写一个 read_only public member,它就是主动绕过 Structive contract。

原则

Structive 服务于遵守 managed contract 的代码,不假装能阻止故意绕过系统的 raw C++。

8. Read-Only Metadata 必须产生真实优化

如果一个存储属性无法通过 Structive 被写入,那么不存在另一个 Structive managed writer 与它竞争。

因此 intrinsic read-only 的存储属性:

  • 不分配 lock slot
  • 不贡献 mutex
  • 不受宽泛默认同步模式影响;
  • managed read 不查询 lock slot
  • managed read 不构造 shared_lock

这是 Schema 信息直接产生的结构优化。

原则

如果 Schema 已经证明某项运行时状态没有必要,就不要分配,也不要执行。

9. 编译期信息必须消除运行时工作

Typed API 在编译期知道目标 Property

device.read<&Device::serial_number>();

对于 stored read-only property,编译期路径直接绕过同步。

同样,对只读属性的 typed write 应该通过 requires 从接口中消失,而不是运行后再拒绝。

动态 key API 因为 key 只能运行期确定,所以才做 runtime check。

原则

静态事实优先变成 constexprrequiresif constexpr,不要变成 runtime branch。

10. Synchronization 描述的是可变一致性域

Synchronization 的目的,是协调 mutable managed state。

默认模式:

independent
shared
unsynchronized

Group 让多个可变 Property 共享一个锁域。

Read-only stored property 即使被宽泛规则包含,也会从最终 resolved topology 中移除。

原则

Synchronization 解决 mutable consistency,不解决可见性。

11. Computed Read-Only 是特殊情况

Computed Property 自身可以只读,但它可能依赖可写字段。

Computed value 本身没有可写存储,但读取它时可能需要 mutable dependency 的一致快照。

Synchronized_Computed_Accessor 因此使用 synchronized read view。需要原子一致性的 writable dependency 应和 computed property 处于同一个同步域。

Read-only stored dependency 没有 managed writer,所以可以直接读取而无需锁。

原则

不要给 read-only stored field 创建 mutex。Computed read 的同步只服务于需要一致性的 mutable dependency。

12. 只有一套 Attribute 协议

Core 与 Extension 共用同一套 Attribute mechanism。

Attribute 拥有 category,并可以声明 single-valued 与 inheritable 语义。

UI、serialization、诊断等新领域不应该另起第二套 metadata system。

原则

新的 metadata domain 应扩展 Attribute protocol,而不是创造另一套框架。

13. Category 必须有明确所有者

定义 Attribute category 的组件拥有它的语义。

Presentation 拥有 Presentation Category。Core 可以保存、遍历、泛型读取,但不解释它。

依赖方向保持:

Extension → Core
Core     -X→ Extension

原则

Core 可以存储未知 Extension metadata,但不能学习 Extension 语义。

14. Defaults 只做 Metadata 继承

defaults(...) 用于 inheritable Attribute,不用于偷偷执行行为。

Property-level metadata 可以覆盖同一 single-valued category 的 object default。

Intrinsic capability 不允许继承,因为每个 Property 自己的读写能力必须单独成立。

原则

Defaults 只降低 metadata 重复,不得变成隐藏行为引擎。

15. Validation 必须显式

Constraint 描述有效值,但不自动塞进每次 write()

auto error = validate_property_value<&Device::temperature>(schema, candidate);

单字段 Validation、跨字段 invariant、transaction、rollback 是不同操作。

原则

不要让 write() 变成 validation + event + transaction + rollback 的黑盒工作流。

16. Runtime Access 是适配能力,不是主要编程模型

Property_Object_Base 提供动态 key 的 type-erased access。

Runtime access 只遵守 intrinsic capability,没有 runtime permission mode。

Adapter 自己决定是否暴露某个 Property、是否调用 runtime read/write。

原则

普通 C++ 业务代码优先 member-pointer typed APIruntime access 留给动态边界。

17. Compile-Time Error 与 Runtime Error 分工明确

静态 typed operation 应在编译期拒绝不可能的结构操作,例如:

  • 写 intrinsic read-only property
  • 对 read-only property 请求 typed unique guard
  • 读取 write-only property。

Runtime key API 才使用 Runtime_Access_Result 返回动态错误。Runtime write 明确是 copy-input 边界:intrinsic writable 继续表示结构事实,runtime_copy_writable 单独表示 Accessor 是否能参与 type-erased copy write。这样 move-only typed write 不会被错误描述成结构上不可写。

原则

静态可知的 Property 错误不要拖到运行期。

18. Synchronization Policy 必须保持可替换

Shared_Mutex_Policy 提供真实 shared/exclusive lock。No_Lock_Policy 不保存真实 mutex。

NoLock 不应该分配假的 mutex array,也不应该构造无意义的 lock object。

原则

一个 Policy 移除某项能力时,应尽可能同时移除它的存储和热路径成本。

19. 每实例 Synchronization Override 只让使用者付费

默认 resolved topology 每个类型共享。对象可以显式传入 Property_Synchronization 覆盖。

只有这种对象才保存 override layout。Copy/Move construction 保留该布局;Assignment 保留目标对象自身的 synchronization policy。

原则

默认路径不为少数实例才使用的功能承担存储成本。

20. Extension 自己决定领域行为

Persistence Extension 可以根据自己的 metadata 决定保存字段,GUI 可以决定 editabilityRPC 可以实现 authorization。

这些系统可以读取 Structive 的 readablewritablesensitive 或自定义 Attribute,但 Structive 不替它们做策略决定。

原则

Core 描述结构,Consumer 在自己的边界决定行为。

21. Core 的非目标

Property Core 不准备成为:

  • Authorization Engine
  • ORM
  • JSON Library
  • RPC Framework
  • GUI Binding Framework
  • Transaction Manager
  • Event Bus
  • Scripting Engine。

这些系统可以消费 Structive,但应该独立存在。

22. 演进审核规则

以后扩展 Structive 时逐条检查:

  1. 它是在增强普通 C++,还是替代普通 C++?
  2. 这个信息属于类型还是实例?
  3. 这是 intrinsic structural capability,还是外部 policy
  4. 编译期信息能不能直接消掉运行时工作?
  5. Read-only stored property 是否仍然完全不进入 lock topology
  6. Synchronization 是否只服务于 mutable consistency
  7. Validation 是否仍然显式?
  8. Extension 是否拥有自己的 category 语义?
  9. Runtime adaptation 是否与 typed business API 保持分离?
  10. 新 Core 概念是否真的普适?

23. 架构总结

最终架构:

Native C++ struct
        │
        ├── raw C++ access
        │
        └── Structive Schema
                │
                ├── intrinsic readable/writable
                ├── Attributes
                ├── Constraints
                ├── synchronization description
                │       └── 只有 mutable consistency domain 创建锁
                └── managed object
                        ├── typed read/write
                        ├── guards
                        ├── traversal
                        └── intrinsic runtime access

External systems
        ├── GUI policy
        ├── RPC policy
        ├── persistence policy
        └── other domain policy

外部 Policy 消费 Structive 的结构事实,但不是 Structive Core 的 access mode。

一句话概括:

Structive 描述 Property 是什么、它自身能做什么;Structive 不决定谁能使用它。