From b67115b50c2a690cd216b1f903caf7f7456c8560 Mon Sep 17 00:00:00 2001 From: skycurtain Date: Wed, 4 Feb 2026 13:31:54 +0800 Subject: [PATCH] =?UTF-8?q?refactor(array-tracer):=20=E7=A7=BB=E9=99=A4=20?= =?UTF-8?q?preset=20=E6=8C=87=E4=BB=A4=E5=B9=B6=E7=AE=80=E5=8C=96=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 preset 功能合并到 create 指令中,简化 API 设计 - 移除 ArrayTracerPresetCommand 类型及相关处理逻辑 - 调整 createArrayTracer 泛型参数以直接接受数组类型 - 更新相关文档以反映新的初始化模式 --- .trae/documents/cross-language-sdk-guide.md | 20 ++++++------- .../documents/sdk-initialization-patterns.md | 29 +++++++++++++------ tracers.ts/src/index.ts | 2 +- tracers.ts/src/tracers/array-tracer.ts | 20 +++---------- tracers.ts/src/types/array-tracer.ts | 8 ----- 5 files changed, 34 insertions(+), 45 deletions(-) diff --git a/.trae/documents/cross-language-sdk-guide.md b/.trae/documents/cross-language-sdk-guide.md index 668b588..270295e 100644 --- a/.trae/documents/cross-language-sdk-guide.md +++ b/.trae/documents/cross-language-sdk-guide.md @@ -4,6 +4,8 @@ Structrail 平台的核心目标是提供一套**语言无关**的数据结构可视化协议。这意味着我们的 SDK 需要在不同特性的编程语言中(从高动态的 Python/JS 到静态底层的 C/C++)提供一致的功能体验。 +**注意,我们不再需要 `preset` 指令了,但是即便 `preset` 的参数被合并到 `create` 指令中,这篇文档对于如何在不同语言中实现 `preset` 功能的说明仍然是有价值的。** + 其中,`preset` 指令(一次性同步数组/容器状态)在静态类型语言(特别是 C 语言)中的实现是最大的挑战。本文档旨在论证其可行性,并为未来各语言 SDK 的实现提供参考规范。 ## 核心挑战:数组的异构性 @@ -17,20 +19,17 @@ Structrail 平台的核心目标是提供一套**语言无关**的数据结构 为了抹平差异,我们建议 SDK 接口设计遵循\*\*“渐进式暴露”\*\*原则: 1. **Level 1: 智能推断接口**(针对 TS, Python, Java 等) + - 用户直接传数组对象。 + - SDK 内部自动获取长度、遍历序列化。 - * 用户直接传数组对象。 - - * SDK 内部自动获取长度、遍历序列化。 2. **Level 2: 显式元数据接口**(针对 C++, Go, Rust 等) + - 用户传递数据指针 + 长度。 + - 利用泛型/模板自动推导元素序列化逻辑。 - * 用户传递数据指针 + 长度。 - - * 利用泛型/模板自动推导元素序列化逻辑。 3. **Level 3: 手动序列化接口**(针对 C 语言) + - 用户传递数据指针 + 长度 + 元素大小 + 序列化策略。 - * 用户传递数据指针 + 长度 + 元素大小 + 序列化策略。 - -*** +--- ## 各语言实现参考 @@ -156,7 +155,7 @@ tracer_preset_cb(t, nums, 3, sizeof(int), my_int_serializer); "tracer": "uuid-...", "action": "preset", "params": { - "data": [1, 2, 3, 4] // 或者是 [{"x":1,"y":2}, ...] + "data": [1, 2, 3, 4] // 或者是 [{"x":1,"y":2}, ...] } } ``` @@ -167,4 +166,3 @@ tracer_preset_cb(t, nums, 3, sizeof(int), my_int_serializer); 1. **`preset`** **指令是可移植的**:即使在最底层的 C 语言中,通过适当的 API 封装(宏或格式化串),也能实现与高级语言近似的开发体验。 2. **不要为了 C 语言阉割协议**:不需要因为 C 语言处理数组麻烦,就放弃 `preset` 而强迫所有语言都用 `patch` 循环。SDK 应该把复杂性封装在内部,留给用户简洁的接口。 - diff --git a/.trae/documents/sdk-initialization-patterns.md b/.trae/documents/sdk-initialization-patterns.md index 3e6cef9..8a4e489 100644 --- a/.trae/documents/sdk-initialization-patterns.md +++ b/.trae/documents/sdk-initialization-patterns.md @@ -1,11 +1,13 @@ # 多语言 SDK 初始化设计规范 ## 背景 + 为了简化 SDK 的使用流程并统一 API 设计体验,我们决定将 Tracer 的初始化数据(Initial Data)合并到创建(Create)阶段。这意味着用户在实例化 Tracer 时,可以直接传入初始数据,而无需单独调用 `preset` 方法。 这一设计模式(Construct as Initialize)在大多数现代编程语言中都有成熟的最佳实践。本文档旨在为不同语言的 SDK 实现提供具体的代码范式参考。 ## 核心原则 + 1. **优先使用构造函数参数**:如果语言支持(如 Python, Kotlin, Swift),优先使用带默认值的命名参数。 2. **利用语言特性**: - **重载 (Overloading)**:适用于 Java, C++, C#。 @@ -18,6 +20,7 @@ ## 各语言实现参考 ### 1. TypeScript / JavaScript (当前基准) + 利用接口(Interface)定义配置对象,简洁且扩展性强。 ```typescript @@ -31,13 +34,14 @@ export const createArrayTracer = (options: ArrayTracerOptions) => { ... } // 调用 const t1 = createArrayTracer({ description: "Empty" }); -const t2 = createArrayTracer({ - description: "My Array", - array: [1, 2, 3] +const t2 = createArrayTracer({ + description: "My Array", + array: [1, 2, 3] }); ``` ### 2. Python (Keyword Arguments) + 利用 `**kwargs` 或显式关键字参数,非常符合 Pythonic 风格。 ```python @@ -53,6 +57,7 @@ t2 = ArrayTracer(description="My Array", data=[1, 2, 3]) ``` ### 3. Java (Constructor Overloading) + 利用构造函数重载提供多种初始化路径。 ```java @@ -74,6 +79,7 @@ var t2 = new ArrayTracer("My Array", Arrays.asList(1, 2, 3)); ``` ### 4. C++ (Overloading & Initializer List) + 利用 `std::initializer_list` 支持花括号初始化,语法极其简洁。 ```cpp @@ -82,10 +88,10 @@ class ArrayTracer { public: // 基础构造 ArrayTracer(std::string description) { ... } - + // 带数据构造 (支持 vector) ArrayTracer(std::string description, const std::vector& data) { ... } - + // 带数据构造 (支持 {1,2,3} 字面量) ArrayTracer(std::string description, std::initializer_list data) { ... } }; @@ -96,6 +102,7 @@ ArrayTracer t2("My Array", {1, 2, 3}); ``` ### 5. Go (Functional Options Pattern) + Go 社区处理复杂构造参数的标准模式。 ```go @@ -121,6 +128,7 @@ t2 := NewArrayTracer("My Array", WithData([]interface{}{1, 2, 3})) ``` ### 6. Rust (Builder Pattern) + 利用 Builder 模式处理构造参数,保证类型安全和可读性。 ```rust @@ -142,6 +150,7 @@ let t = ArrayTracer::builder("My Array") ``` ### 7. C# (Optional Arguments) + 类似于 TypeScript 和 Kotlin,C# 支持命名参数和默认值。 ```csharp @@ -157,6 +166,7 @@ var t2 = new ArrayTracer("My Array", data: new[] { 1, 2, 3 }); ``` ### 8. C 语言 (Special Case) + C 语言不支持重载,且缺乏自省能力,因此建议提供两种创建模式: **方案 A: 基础数据类型 (使用宏或特定后缀)** @@ -186,10 +196,10 @@ typedef void (*serializer_func)(const void* elem, char* buffer); * @param serializer 用户提供的序列化函数 */ tracer_t* tracer_create_array_custom( - const char* desc, - const void* data, - size_t len, - size_t elem_size, + const char* desc, + const void* data, + size_t len, + size_t elem_size, serializer_func serializer ); @@ -210,4 +220,5 @@ tracer_t* t = tracer_create_array_custom("Points", pts, 2, sizeof(Point), point_ --- ## 总结 + 通过统一采用**“构造即初始化”**的设计模式,我们能够在几乎所有主流编程语言中提供一致、简洁且符合语言习惯(Idiomatic)的 SDK 使用体验。这不仅降低了用户的学习成本,也使得代码更加紧凑和易读。 diff --git a/tracers.ts/src/index.ts b/tracers.ts/src/index.ts index c962e92..a6de801 100644 --- a/tracers.ts/src/index.ts +++ b/tracers.ts/src/index.ts @@ -8,7 +8,7 @@ import { const logTracer = createLogTracer({ description: 'LogTracer' }); const controlTracer = createControlTracer({ description: 'ControlTracer' }); -const arrayTracer = createArrayTracer({ +const arrayTracer = createArrayTracer({ description: 'ArrayTracer', array: [1, 2, 3], }); diff --git a/tracers.ts/src/tracers/array-tracer.ts b/tracers.ts/src/tracers/array-tracer.ts index 38f28e8..b54c28d 100644 --- a/tracers.ts/src/tracers/array-tracer.ts +++ b/tracers.ts/src/tracers/array-tracer.ts @@ -1,12 +1,12 @@ import { getTracerContext } from '../context'; import type { JsonValue } from '../types'; -interface ArrayTracerCreateOptions { +interface ArrayTracerCreateOptions { description?: string; - array?: T[]; + array?: T; } -export const createArrayTracer = ( +export const createArrayTracer = ( options: ArrayTracerCreateOptions, ) => { const { description = 'ArrayTracer', array } = options; @@ -24,17 +24,6 @@ export const createArrayTracer = ( }, }); - const preset = (array: T[]) => { - command({ - type: 'ArrayTracer', - tracer: tracer, - action: 'preset', - params: { - array: array, - }, - }); - }; - const scale = (size: number) => { command({ type: 'ArrayTracer', @@ -68,7 +57,7 @@ export const createArrayTracer = ( }); }; - const patch = (index: number, value: T) => { + const patch = (index: number, value: T[number]) => { command({ type: 'ArrayTracer', tracer: tracer, @@ -92,7 +81,6 @@ export const createArrayTracer = ( }; return { - // preset, scale, pick, drop, diff --git a/tracers.ts/src/types/array-tracer.ts b/tracers.ts/src/types/array-tracer.ts index 9f33d8c..944a693 100644 --- a/tracers.ts/src/types/array-tracer.ts +++ b/tracers.ts/src/types/array-tracer.ts @@ -12,13 +12,6 @@ type ArrayTracerCreateCommand = BaseArrayTracerCommand & { }; }; -type ArrayTracerPresetCommand = BaseArrayTracerCommand & { - action: 'preset'; - params: { - array: JsonValue[]; - }; -}; - type ArrayTracerScaleCommand = BaseArrayTracerCommand & { action: 'scale'; params: { @@ -57,7 +50,6 @@ type ArrayTracerUnsetCommand = BaseArrayTracerCommand & { export type ArrayTracerCommand = | ArrayTracerCreateCommand - | ArrayTracerPresetCommand | ArrayTracerScaleCommand | ArrayTracerPickCommand | ArrayTracerDropCommand