Files
Endorphin-Document/guide/11-resource-access-and-presentation.md

173 lines
13 KiB
Markdown
Raw Permalink 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.
# 11. 资源访问与呈现
客户端是 Endorphin 资源的查看与运行环境。它可以访问获准查看的 namespace、函数、类、agent、基础内容和结果值,并根据当前资源的类型及访问状态选择呈现方式。
界面由普通函数返回的可渲染值表达,不使用独立的 scene 声明或 render 块。本章定义资源定位、函数查看、调用、结果呈现及跨端对象关联之间的关系;完整顶级类型集合及呈现契约仍待定义,见[规范状态](../appendices/specification-status.md#资源访问与呈现)。
## 11.1 资源定位与访问
namespace key 定位资源归属及检索范围,函数名、类名或 agent 名选择其中的声明。定位声明、查看定义与发起调用是不同的访问行为;基础内容和实例的成员标识形式仍待定义。
```text
namespace:atelier:shop.pricing
声明:discountedPrice
namespace:atelier:shop.data
声明:Product
```
该示意没有定义 URL、请求协议或新的源码限定名语法。具体名称查找遵守[程序结构与导入](04-program-structure.md)的可见性规则。
| 访问对象 | 当前资源的含义 | 呈现或使用方式 |
| --- | --- | --- |
| namespace | 获准访问的资源组织范围 | 查看允许访问的成员;代码成员形成代码视图 |
| 函数定义 | 参数、返回类型与函数体 | 查看定义,或准备相应调用 |
| 类定义 | 类型及其结构 | 查看类型定义,不自动取得业务对象 |
| agent 定义 | 成员、工具及运行控制规则 | 查看定义,不自动创建实例或启动任务 |
| 基础内容 | 数值、文本、媒体或 GIS 数据的类型化内容 | 按内容类型使用或呈现,导入编码不直接决定语言类型 |
| 函数调用结果 | 本次执行产生的值 | 按结果类型呈现,或供后续程序使用 |
查看 namespace 不表示执行其中全部函数,也不保证包含全部下级 namespace。查看定义的权限与调用权限分别适用;代码定位本身不授予权限。
读取实现源码使用 r,编辑资源使用 w,使用已定义的程序能力使用 x。调用按业务契约产生写入不因此要求调用者获得整个归属范围的编辑权;只有 x 时的接口信息范围和执行身份仍待定义,见[用户身份与 workspace 权限](02-user-identity.md#26-rwx-的操作分工)。
## 11.2 函数本身与返回值
函数本身具有可调用的类型,调用完成后取得的值具有结果类型。二者不能混同;尚未调用时,返回类型描述结果约束,不表示结果已经存在。
以下示例使用[函数与调用](09-functions-and-calls.md)中的声明,假定 discountedPrice 可查看且可调用:
```text
查看 atelier:shop.pricing 中的 discountedPrice
→ 取得函数定义
提供 price = 100、discount = 10 并调用
→ 取得结果 90
```
前一种访问查看函数本身,后一种访问处理数值结果。函数没有因为参数未填写而改变类型。
## 11.3 参数就绪与调用状态
客户端访问函数时,如果必要输入尚未提供,应保留对函数本身的查看,可以展示函数签名及获准查看的源码。输入满足调用要求后,可以发起调用,并根据实际返回值选择呈现方式。
此处未填写的输入指调用前尚未绑定的必填参数,不指函数体中的局部变量。默认参数、可省略参数和平台提供参数的具体规则尚未定义。
这一访问行为不改变普通调用表达式的参数检查:业务源码中缺少必填参数的调用仍应得到诊断,不能静默转换成源码查看。
| 状态 | 客户端当前处理的内容 |
| --- | --- |
| 必填参数尚未就绪 | 函数本身,不执行尚不满足输入要求的调用 |
| 调用已开始,结果未就绪 | 本次调用的等待状态,或已经可用的部分界面 |
| 调用成功 | 符合声明的结果值,按其类型处理 |
| 调用失败 | 本次执行失败,不伪造成功结果 |
等待后端结果不等于缺少调用参数,不能因此退回为函数源码展示。具体参数填写界面和状态呈现形式仍待定义。
## 11.4 普通函数与界面结果
函数使用普通参数、表达式、调用与 return 表达界面逻辑。客户端取得可渲染类型的结果后渲染界面;其他结果依据相应类型的呈现约定处理。界面构造表达式与可渲染类型的正式名称尚未定义,本章不引入占位类型或专用 UI 文法。
下面是访问行为示意,不是源码。假定 `market:shop.ui` 中存在可访问的 productPage,接收一个商品编号,并返回可渲染值:
```text
打开 productPage,尚未提供商品编号
→ 查看函数定义
提供商品编号 p1001 并调用 productPage
→ 取得该商品的界面值
→ 客户端渲染界面
```
函数内部产生的界面值也可以交给其他函数组合或使用。这里的自动呈现针对客户端当前打开的资源或调用结果,不要求每个中间结果都显示到屏幕上。
返回类型约束结果的用途,不单独决定函数的执行位置。普通业务函数、界面函数和类型声明共用 namespace 的组织方式。
## 11.5 跨端调用与持续更新
前端通过函数调用请求结果,通过 hook 关联持续更新。hook 表示触发或订阅关系,可用于界面、后端逻辑及其他数据同步用途;其源码形式与生命周期边界尚未定义。
系统依据调用依赖与 hook 关系组织相关执行,包括需要在后端解释执行的逻辑,并将结果交给前端使用。前后端的通信由平台承担;应用代码直接使用符合声明类型的值,不要求自行解析传输响应或恢复业务对象类型。
```text
客户端执行界面逻辑
→ 调用数据函数或建立 hook 关联
→ 系统组织后端执行并交付结果
→ 客户端使用结果或后续更新,调整界面
```
一次调用与持续结果的区别见[数据读取](10-data-access.md#105-一次读取与持续结果)。自动更新的范围、业务修改的重复执行规则及取消行为仍待定义;依赖关系不自动授权系统重复执行所有相关函数。
客户端通过本地对象使用远程数据时,其与平台对象的身份关联、数据传递及后续同步见[跨端对象与同步](#117-跨端对象与同步)。hook 可以参与更新关联,但不因此替代对象身份或数据存储。
## 11.6 按类型呈现的边界
按资源类型选择处理方式是客户端的呈现方向。基础数值、文本、媒体与 GIS 类别及其格式归一化见[资源、类型与类](07-types-and-classes.md);agent 的使用语义见[Agent](13-agents.md)。顶级类型的候选操作与代码见[逐项设计](07-top-level-types/README.md);完整类型名称、能力组合和展示契约的确定程度统一记录在[规范状态](../appendices/specification-status.md#资源访问与呈现)中。
平台不能仅凭对象字段或方法的结构认定其属于可渲染类型或实现了展示能力。类型身份与兼容规则见[类型与类](07-types-and-classes.md#76-类型身份与兼容);具体展示能力关系仍待定义。
本章不规定普通对象必须继承界面类型,也不指定数据查看器、媒体播放器或代码查看器的实现。官方 UI 组件的现有效果提案见[UI 组件](12-ui-components.md)。
## 11.7 跨端对象与同步
Endorphin 对象可以由平台识别、管理和存储,其存续不必绑定到某次客户端运行或某台机器的内存。客户端需要使用远程对象的数据时,可以建立本地对象,并关联到平台管理的同一对象;后续变化通过网络同步到本地。
这里的“平台对象”描述已有 Object 模型的管理方式,不另设 PlatformObject 基础类型,也不表示所有临时值都必须永久登记。对象类型、atom 与资源 ID 的主要定义见[Object、atom 与资源 ID](07-top-level-types/README.md#objectatom-与资源-id)。
### 对象身份与本地副本
平台保存的是对象的身份、类型关联及需要保留的内容或状态。执行代码使用它时,仍需要在执行端准备相应的内存表示;平台存储并不消除运行时内存。
客户端为远程对象准备的本地对象称为本地副本。它保存已取得的类型化数据及目标对象的身份关联,供本地代码读取或使用。客户端和服务器上的物理表示分别占用各自的内存;通过资源 ID 关联到同一逻辑对象,不表示共享同一个内存地址。
| 层次 | 表达什么 | 不单独保证什么 |
| --- | --- | --- |
| 平台对象身份 | 正在关联哪一个对象 | 对象的当前状态已经到达客户端 |
| 平台保存的内容或状态 | 对象在平台中的保留信息 | 每个执行端都已加载完整内容 |
| 本地副本 | 当前执行端已经取得、可以使用的数据 | 数据始终最新,或本地修改已经保存 |
| 同步关联 | 后续变化继续传递到关联的副本 | 多端瞬时一致,或任意冲突自动解决 |
本地副本的关联身份不代替类型检查和访问授权。平台按已确定的对象类型恢复可使用的数据,不仅凭收到的字段结构认定其类型。
### 获取与后续同步
下面描述平台职责,不规定源码接口、传输编码或服务器部署方式:
```text
客户端请求关联一个获准访问的对象
→ 平台解析目标身份并取得可交付的内容或状态
→ 数据通过网络传到客户端
→ 客户端准备类型化的本地副本,保留目标身份关联
→ 建立持续关联后,后续变化继续通过网络传递
→ 客户端更新可使用的本地数据
```
一次读取只取得该次结果;建立持续关联后,才具有跟随后续变化的语义。因此,读取对象不自动表示永久订阅,关联同一对象也不表示各端此刻拥有同样的数据。
同步遵守对象自身的更新契约。内容对象和定义对象的修改产生新的资源 ID,已保存的确定引用继续指向原对象;同步不能把这种引用静默改成新定义。类型允许改变状态的运行对象则可以保留身份,并把合法的状态变化交付给本地副本。跟随命名入口选用新对象与同步同一运行对象的状态是两种不同关系。
取得代码或函数对象的本地副本只准备了定义。执行函数仍需要满足调用与输入规则;对象关联本身不决定函数何时执行或在哪个执行端运行。Preflight 检查定义及依赖,inflight 管理实际获取、调用与运行状态,阶段名称也不决定执行位置。
### 同一对象可以暂时具有不同的可见状态
沿用商品定价场景,假定 `atelier:shop.pricing` 中有一个允许改变价格引用的共享运行对象,资源 ID 用 `price-state-1` 示意。该名称不规定正式类型或 ID 格式;以下是行为示意,不是源码:
| 时刻 | 平台保存的价格状态 | 客户端 A 的本地副本 | 客户端 B 的本地副本 |
| --- | --- | --- | --- |
| 两端已取得初始状态 | 引用数值 100 | 引用数值 100 | 引用数值 100 |
| 平台已接受一次改价,更新尚未到达 | 引用数值 90 | 仍引用数值 100 | 仍引用数值 100 |
| 更新已到达 A | 引用数值 90 | 引用数值 90 | 仍引用数值 100 |
| 更新已到达两端 | 引用数值 90 | 引用数值 90 | 引用数值 90 |
各端始终关联 `price-state-1`。发生变化的是运行对象的价格引用,不是把常量 100 原地改成 90;两个数值仍分别是不可变内容。
若修改由客户端发起,本地提出修改、平台接受修改和其他副本收到更新也是不同的时刻。不能仅凭本地赋值或界面已显示新值,就认定平台已经接受并保存修改。是否允许提前展示本地修改、如何确认结果以及如何处理同时改价,统一保留在[跨端对象与同步的规范状态](../appendices/specification-status.md#跨端对象与同步)。
### 副本、关联与平台对象的生命周期
关闭客户端、释放本地副本或解除同步关联,不等于删除平台对象。对象是否继续保留遵守平台的生命周期和有效保留根规则;由平台存储也不表示永不回收。客户端再次访问时可以重新取得数据,恢复到哪个状态以及怎样接续遗漏的更新仍待定义。
对象尚未取得、连接中断、更新失败和目标已不可访问,需要与成功取得数据区别处理。具体状态类型、授权撤销后的行为、删除规则及关联解除接口尚未定义,不能把这些情况伪装成正常的空对象或零值。
[上一章:数据读取](10-data-access.md) · [下一章:UI 组件](12-ui-components.md) · [目录](../README.md)