跳到主要内容

理论核心

提示
  • Nop 平台还处于开发阶段, 本文档中的实践方案可能会部分失效,但本人精力有限,无法及时跟进,请自行按照最新代码调整;
  • 您可以与智谱清言 AI 进行问答互动以了解 Nop 平台相关内容;
  • 若此文对您有很大帮助,请投币支持一下吧;
版权声明

注意,此文为思维碎片,还未整理成文。

  • 信息空间中最有效的生产方式不是组装,而是掌握和制定运算规则
  • Nop 不仅仅是一种具体的开发框架,它更是一种新的思维方式。 Nop 解决问题的方式是先定义一个 DSL 语言去建立局部的描述框架, 相当于是在广袤的模型空间中建立一个个的据点, 然后不同的模型之间再建立自动转换的技术路径, 通过完全自动化的推理就可以在模型空间中自由通行

差量 - Delta

  • 差量在本质上描述的是系统的变化过程,是一种向系统施加变化的工具,并且具备时间回溯能力
  • 应用开发不能只有增量,还必须有减量,增量和减量合称为差量
  • 通过差量可以支持相似可复用,而不再是相同可复用。 可以充分利用相似性以最大限度地提高系统的可复用性,并保证支持对差异化的能力开发
  • 可最大限度地降低系统熵增的速率,保证系统的不断演化
  • 定制化代码相当于是一种针对基础产品的 Delta 修正
  • 差量 Delta 应该是架构设计中的第一类(First Class)概念。 这样它才可以被独立识别、管理、存放。 定制化代码应该和基础产品代码在物理层面分离,单独进行版本管理
  • 全量是差量的一个特例
  • Delta 可以脱离基础产品,独立的对多个 Delta 进行合并运算, 将多个 Delta 打包为一个整体
  • Delta 必须包含逆元,这样才能实现对原系统的剪裁。 Delta 应该是新增、修改、删除的混合体
  • 系统需具备一个稳定的定位坐标系。 dA 与 A 分离之后,存放到独立存在的 Delta 中,那么它必然保留了某种定位坐标, 只有这样,当 Delta 与 X 结合的时候,才可以重新找到原始的结构 A,然后与 A 相结合
    • 坐标系是指能够唯一定位到各个模型具体属性的方式方法
  • Delta 可以理解为应用在不可变数据不可变逻辑之上的一种变更机制, 也就是,被修改的数据或函数是不可变的,若要对其进行调整, 就需要通过差量技术层层记录针对上一层的差量,再统一进行合并, 合并后的结果便是最终的状态

状态驱动 - State Driven

https://zhuanlan.zhihu.com/p/85492497#h_85492497_4

  • 关注的重点是系统的状态以及状态之间的差异,而不再是传统的基于动作概念的 API 调用和事件监听
  • 从状态 A 迁移到状态 B,无论经过什么路径,最终得到的结果都是一样的,是路径无关的。 摆脱了路径依赖极大简化了我们对系统的认知
  • 从状态 A 迁移到状态 B 有多条可行的路径,在这些路径中按照成本或者收益原则选择其一, 这就是所谓的优化

注:状态的迁移,才是更加符合现实世界的内在驱动模式。

DSL

  • 属于编译期技术方案,需要将 DSL 编译后才能得到可执行的逻辑
  • 通过 DSL 提取并抽象应用功能模块
  • 一个应用就是一片 DSL 森林
  • 不同的层级有不同的 DSL(多级抽象),从上至下,DSL 的细节会越来越多
  • DSL 与具体的代码实现无关,它描述的是要做什么,而不关心该怎么做
    • DSL 是一种表达运行分离方案
  • 相同的模型具有不同的形态和表现形式,可以通过 DSL 支持不同的表达方式
    • 例如,<and><eq name="status" value="1" /><gt name="amount" value="3" /></and> 展现在前台,便对应于一个查询表单,应用到后台,则对应于 Predicate 接口的实现, 发送到数据库中,则转化为 SQL 过滤条件的一部分。 而这一切,并不需要人工编码,它们只是同一信息的多重诠释而已
  • 支持差量合并,以实现 DSL 复用和扩展
  • 通过前缀引导实现 DSL 的分层设计, 支持多种风格的 DSL,可同时在 XML DSL 中引入代码(代码也是一种 DSL)。 不同的 DSL 由不同的解释器解析后再合并到上层 DSL AST 树中, 当前层的 DSL 解释器不需要理解和关注其他层的 DSL 结构和符号。 除了父子节点的 DSL 形式,还可以通过 XML Namespace 在 DSL 节点上标注 其他层的属性(比如,<prop name="abc" graphql:labelProp="abc_label"/>), 从而在当前 DSL 层附加上其他层的额外信息,可被 GraphQL 层直接识别和处理
  • 一个 DSL 包含 引入xmlns:xx)、扩展extends)、结构schema)三个外部源。 引入可以通过名字空间使用其他 DSL 层的属性和标签,从而支持同一份 DSL 可进行多种形式的表达, 扩展就是在其他 DSL (可以是不同层)的基础上进行差量调整以达到当前 DSL 的需求, 而结构则是用于限定当前 DSL 结构的(限定可用节点名称、属性类型等)
  • 不同的编程语言的实现就是一个个不同的坐标系统,相同的 DSL 可以在不同的坐标系统中进行表达, 也就是,DSL 是语言无关的,可以有多种实现方式

XLang

  • XDef 是 XLang 中的领域模型定义语法,用于定义模型结构,约束属性数据, 作用类似于采用 XML 语法的 XSD 语言和采用 JSON 语法的 JSON Schema。 XDef 与它们的区别在于,它强调两点:
    • schema 描述与领域描述本身是同形的,也就是说schema 的 Tree 结构与领域模型的 Tree 结构是一致的
    • 所有的集合元素都通过 xdef:key-attr 定义有唯一属性,从而确保领域描述的每个节点都有稳定且唯一的 xpath 路径
  • 对于每一个集合元素,XDef 需要明确定义用于区分不同子元素的唯一属性,借助这一属性, 可以高效、稳定的实现领域结构的 diff 算法(类似于 vue 框架中虚拟 DOM 的 diff), 因此使用 XDef 定义一个领域结构,同时也意味着定义了该领域结构的差量化结构,我们可以很容易的计算两个领域结构的差与和
  • 内置 x:extendsx:gen-extends 语法结构,所有 DSL 自动具有差量编程元编程的能力, 可以自由调用所有 Xpl 标签库,无需额外设计继承、库等抽象机制
  • XLang 中不同的 DSL 共享了同样的扩展机制,使得它们只需要关注最核心的领域模型结构即可, 而 x:gen-extends 的全部作用可以被看作是编译期的一种代码生成技术(产生式编程), 简单的说就是不断拼接、转换、输出字符串或者 XNode,无论内部执行过程多复杂, 引入多少 XPL 标签库,最终实际送到 DSL 解析器里的只有符合 XDef 定义的 DSL 模型文本

结构化

  • 核心为树结构,开发应用的过程,就是调整树结构的过程
  • 一个应用就是一颗,其中的模型就是子树
  • 将数据结构化,可以避免在对象跨边界交换时出现信息丢失,使得对信息的自动化处理成为可能
  • 可逆计算强调逻辑结构的可逆转化,也就是在系统 A 中需要保留一些元信息(metadata) A', 以便于可以从系统 A 直接转换为系统 B,也需要在系统 B 中保留元信息 B', 从而实现从系统 B 转换为系统 A。 (data, metadata) 配对才是信息的完整表达, 这和消息对象总是包含 (body, headers) 是一个道理