Files
Structive/docs/EXTENSIONS.zh-CN.md
T
2026-08-07 17:50:04 +08:00

271 lines
6.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Structive Extension 架构指南
[English](EXTENSIONS.md)
## 1. Extension 的职责
Extension 给 Structive 增加领域 metadata 与领域解释,但不能让 Property Core 反向依赖具体领域。
依赖方向:
```text
Extension → Property Core
Property Core -X→ Extension
```
Core 提供:
- Schema 与 Property Descriptor
- intrinsic readable/writable
- Attribute 协议;
- Constraint
- Synchronization metadata 与 managed access
- Runtime structural access。
Extension 定义自己的 category 与解释逻辑。
## 2. Extension 基本原则
Extension 只拥有自己的领域语义。
例如 Presentation 拥有:
```text
label
description
group
order
```
Property Core 不需要理解 presentation。
未来 Persistence Extension 可以拥有自己的持久化 metadataRPC Extension 可以拥有协议 metadata。
## 3. 外部 Policy 永远属于外部
Property Core 完全没有内建访问控制模式。
Extension 或应用层自己负责:
```text
这个属性要不要显示?
这个 endpoint 要不要允许写?
这个 Property 要不要持久化?
当前用户是否有权限?
```
Extension 可以读取结构事实:
```text
Property::readable
Property::writable
sensitive metadata
Extension 自己的 metadata
```
但最终 policy 属于 Consumer。
`read_only` 只表示 Structive managed object 自身没有这个 Property 的写操作,不代表任何外部系统必须暴露它。
## 4. 当前 Presentation Extension
Include
```cpp
#include <structive/property/extensions/presentation.hpp>
```
Link
```cmake
target_link_libraries(my_target PRIVATE structive::property_extensions)
```
当前 Attribute
```cpp
presentation::label<"Temperature">
presentation::description<"Current device temperature">
presentation::group<"Environment">
presentation::order<2>
```
示例:
```cpp
field<&Device::temperature>(
key<"temperature">,
unit<"C">,
presentation::label<"Temperature">,
presentation::description<"Current device temperature">,
presentation::group<"Environment">,
presentation::order<2>
)
```
## 5. Presentation 解释
```cpp
auto info = presentation::describe<&Device::temperature>(device.schema());
```
`Presentation_Info`
```text
key
label
description
group
order
has_order
```
没有 label 时,Presentation Extension fallback 到 Property key。这个 fallback 属于 Presentation,不属于 Core。
## 6. 可继承 Extension Attribute
Extension category 可以选择 inheritable
```cpp
defaults(
presentation::group<"Environment">
)
```
Property-level metadata 覆盖同 category 的 inheritable single-valued default。
只有真正适合继承的 metadata 才应该这样设计。
## 7. 设计新的 Extension Attribute
```cpp
namespace my_extension {
struct Format_Category {};
template <Fixed_String Value>
struct Format_Attribute {
using attribute_category = Format_Category;
static constexpr bool single_valued = true;
static constexpr bool inheritable = false;
static constexpr auto value = Value;
};
template <Fixed_String Value>
inline constexpr Format_Attribute<Value> format{};
}
```
直接挂在 Property
```cpp
field<&Device::temperature>(
key<"temperature">,
my_extension::format<"0.0 C">
)
```
不需要修改 Core。
## 8. 读取 Extension Attribute
Descriptor-local metadata
```cpp
using Property = std::remove_cvref_t<decltype(schema.property<&Device::temperature>())>;
static_assert(Property::template has_attribute<my_extension::Format_Category>);
```
可继承 metadata 可以使用 Core 的通用 effective-Attribute 工具。
Fallback 和解释规则由 Extension 自己拥有。
## 9. Multi-Valued Metadata
如果 category 不是 single-valuedExtension 可以允许同 category 多个 Attribute。
只有重复声明本身结构非法时才应该设置 `single_valued = true`
## 10. 推荐 Extension 边界
适合的领域包括:
- Presentation / Editor Hint
- Serialization Name / Format Hint
- Persistence Mapping Metadata
- RPC / Protocol Naming Metadata
- Diagnostics / Telemetry Metadata
- Documentation Metadata。
领域实现继续放在 Property Core 外部。
## 11. 使用 Intrinsic Capability
Consumer 可以把 intrinsic capability 当作结构事实。
例如 Editor 可以先用:
```cpp
Property::writable
```
判断一个 Property 是否具备“可编辑的结构资格”,但 Editor 仍然可以叠加自己的应用 policy。
Persistence Adapter 即使看到 `Property::readable == true`,也完全可以决定不保存它。
RPC Endpoint 即使看到一个 Property writable,也可以完全不暴露它。
这种分离是刻意设计。
## 12. Read-Only 优化属于 Core 保证
Extension 不需要为 stored `read_only` Property 自己实现特殊锁逻辑。
Core 保证这类 Property 不贡献 lock slot 和 mutexmanaged read 走 no-lock path。
如果 Extension 故意通过 raw C++ 写它,就已经绕过该保证,同步责任由 Extension 自己承担。
## 13. Fallback 属于 Consumer
Core 不应该决定:
```text
没有 label -> key
没有 database column -> key
没有 RPC name -> key
```
这些 fallback 属于对应 Extension 或 Adapter。
## 14. 防止 Extension 语义泄漏进 Core
不要因为一个 Extension 需要某个概念,就给 Core 增加特殊 enum 或分支。
优先:
```text
Extension-owned Attribute category
+ Extension-owned interpretation
```
而不是:
```text
Core 学会 Extension 领域语义
```
## 15. Header-Only Metadata 与 Linked Code
Metadata 类型通常可以保持 header-only。领域确实需要非模板 runtime behavior 时,再放 linked implementation。
当前 Presentation Extension 把 metadata 放头文件,把 `make_presentation_info` 放 linked target。
## 16. Extension 审核清单
新增 Extension feature 前检查:
1. Core 是否已经提供所需的通用结构机制?
2. 能否表达成 Extension-owned Attribute
3. Fallback 是否由 Extension 自己拥有?
4. Access / Exposure Policy 是否仍在 Core 外?
5. 是否把 intrinsic `readable/writable` 当结构事实,而不是 authorization
6. 是否避免无意 raw write 绕过 managed synchronization
7. Core 是否仍完全独立于 Extension