Skip to content

Commit 8b02deb

Browse files
committed
docs: synced via GitHub Actions
1 parent 2dc4ca1 commit 8b02deb

File tree

2 files changed

+93
-16
lines changed

2 files changed

+93
-16
lines changed

src/theory/reversible-computing-theory-overview.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -115,13 +115,13 @@ DDD的传统理解是围绕"**语义、约束、演化**"三类不变性:
115115
可逆计算的视角将我们从"存在"的本体论,引向了"生成"的演化论。我们对软件的理解,从静态的、孤立的"实体",转向了动态的、关联的"过程"。这一理论不仅提供了具体的技术解决方案,更重要的是提供了一种理解软件构造和演化的全新思维框架,为应对日益复杂的软件系统提供了理论基础和实践路径。
116116

117117
## 参考文档
118-
- [可逆计算:下一代软件构造理论](https://mp.weixin.qq.com/s/CwCQgYqQZxYmlZcfXEWlgA)
119-
- [DDD本质论之理论篇](https://mp.weixin.qq.com/s/xao9AKlOST0d97ztuU3z9Q)
120-
- [DDD本质论之实践篇](https://mp.weixin.qq.com/s/FsrWW6kmOWHO0hQOS2Wj8g)
121-
- [对DDD本质论一文的解读](https://mp.weixin.qq.com/s/6bONsaTE79shhSHfrKiyMw)
122-
- [广义可逆计算: 一个软件构造范式的正名与阐释](https://mp.weixin.qq.com/s/pNXPEvyVB7ljOhBQVh6c-A)
123-
- [从可逆计算看Delta Oriented Programming](https://mp.weixin.qq.com/s/XQlzQSGo-gqColvDw7UPyA)
124-
- [Nop如何克服DSL只能应用于特定领域的限制?](https://mp.weixin.qq.com/s/6TOVbqHFmiFIqoXxQrRkYg)
118+
- [可逆计算:下一代软件构造理论](https://mp.weixin.qq.com/s/CwCQgYqQZxYmlZcfXEWlgA):对可逆计算理论的概要介绍,阐述了其基本原理、核心公式,以及与图灵机、Lambda演算这两种传统计算世界观的区别,定位为第三条通向图灵完备的技术路线。
119+
- [DDD本质论之理论篇](https://mp.weixin.qq.com/s/xao9AKlOST0d97ztuU3z9Q): 结合(广义)可逆计算理论,从哲学、数学到工程层面,系统性地剖析了DDD(领域驱动设计)的技术内核,认为其有效性背后存在着数学必然性。
120+
- [DDD本质论之实践篇](https://mp.weixin.qq.com/s/FsrWW6kmOWHO0hQOS2Wj8g):作为理论篇的续篇,重点介绍了Nop平台如何将可逆计算理论应用于DDD的工程实践,将DDD的战略与战术设计有效地落实到代码和架构中,从而降低实践门槛。
121+
- [DDD本质认知的演进:从实践框架到构造理论](https://mp.weixin.qq.com/s/6bONsaTE79shhSHfrKiyMw): 通过AI辅助的思想实验,对比了传统的DDD概念框架与《DDD本质论》中从第一性原理(空间、时间、坐标系、差量)出发的推导路径,揭示了后者更深刻的内在逻辑。
122+
- [广义可逆计算: 一个软件构造范式的正名与阐释](https://mp.weixin.qq.com/s/pNXPEvyVB7ljOhBQVh6c-A):为“广义可逆计算”(GRC)正名,阐释了其核心思想——以“差量”(Delta)为第一类公民,系统性地管理软件构造过程中的可逆性与不可逆性,旨在解决“复杂性”这一核心工程难题。
123+
- [从可逆计算看Delta Oriented Programming](https://mp.weixin.qq.com/s/XQlzQSGo-gqColvDw7UPyA):对比了可逆计算与学术界的面向特征编程(FOP)和面向差量编程(DOP)等理论,指出可逆计算通过引入“场”和“坐标系”的观念,能更有效地管理“预料之外的变化”。
124+
- [Nop如何克服DSL只能应用于特定领域的限制?](https://mp.weixin.qq.com/s/6TOVbqHFmiFIqoXxQrRkYg):解释了Nop平台如何通过横向(多DSL组合成特性空间)和纵向(多阶段、多层次生成)的分解,克服传统DSL只能应用于特定领域的限制,实现图灵完备的表达能力。
125125

126126
## 附录:可逆计算是不是一种典型的霸总思维~既要又要还要~
127127

src/theory/why-composition-over-inheritance.md

Lines changed: 86 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ superHero.learnAbility(new InvisibleAbility());
8686

8787
**实践总结**:继承意味着强耦合、静态结构和脆弱性;组合提供了松耦合、动态结构和健壮性。在需要应对变化和演进的复杂系统中,组合无疑是更明智的选择。
8888

89-
这个层面的理解虽然正确,但主要停留在现象描述。现在,让我们深入探索其背后的数学本质
89+
这个解释是正确的,但它主要回答了'是什么'和'有什么好处'。现在,让我们深入到'为什么'的数学本质
9090

9191
## 第二部分:数学本质的深刻洞察
9292

@@ -95,14 +95,16 @@ superHero.learnAbility(new InvisibleAbility());
9595
1. **继承的数学表达:`A > B ⇒ P(B) → P(A)`**
9696
2. **组合的数学表达:`A = B + C`**
9797

98+
> P(B) → P(A):这是一个逻辑蕴含符号。整个表达式意为:如果某个命题对B为真,那么这个命题对A也必然为真。
99+
98100
前者建立在**逻辑蕴含**之上,后者立足于**代数构造**。我们将看到,从数学视角分析,后者在构建复杂且需要持续演化的软件系统时,具有根本性的优势。
99101

100102
### 继承范式:偏序关系与逻辑断言
101103

102104
**类继承作为偏序关系**
103105

104-
在数学上,类继承关系 `<:` 构成一个严格的偏序关系,满足:
105-
- **自反性**每个类都是自身的子类型`A <: A`
106+
在数学上,类继承关系 `<:` 构成一个偏序关系,满足:
107+
- **自反性**每个类都是自身的派生类型`A <: A`
106108
- **反对称性**:如果 `A <: B``B <: A`,则 A 和 B 是同一个类
107109
- **传递性**:如果 `A <: B``B <: C`,则 `A <: C`
108110

@@ -111,20 +113,86 @@ superHero.learnAbility(new InvisibleAbility());
111113
**逻辑蕴含的本质**
112114

113115
继承的核心可由公式 `A > B ⇒ P(B) → P(A)` 精确刻画:
114-
- `A > B`(或 `B <: A`)建立了类型偏序关系,断言 `B``A` 的特化
115-
- `P(B) → P(A)` 是其逻辑推论:任何对子类型 `B` 成立的命题 `P`,必然对其父类型 `A` 成立
116+
- ****`A <: B` 是类型理论文献中表达类继承的标准符号,但这里为了数学上的明确性,我们使用 `A > B` 来直观表达"派生类比基类多"的概念
117+
- `A > B` 建立了类型偏序关系,断言 `A``B` 的特化
118+
- `P(B) → P(A)` 是其逻辑推论:任何对基类 `B` 成立的命题 `P`,必然对其派生类 `A` 成立。也就是说,针对基类B编写的一段代码,对于派生类A总是可以编译通过。
116119

117120
这是一种**断言式**的逻辑范式。它声明了 `Dog` 在概念上**属于** `Animal`,但没有阐明 `Dog` 如何被构建。这种范式在概念建模上极具直观美感,完美契合人类对世界的分类直觉。
118121

119122
> 继承的数学表达式 `A > B ⇒ P(B) → P(A)` 可以看作是"里氏替换原则"(LSP)的一种精确数学表达:任何对基类A成立的程序P,对子类B也成立。本质上满足LSP的继承应用才是真正发挥继承威力的地方,一些不满足LSP的应用相当于是一种误用。我们讨论一种技术的本质作用时,当然应该关注其正确应用的场景。
120123
124+
**注意**`A > B`表达了派生类A比基类B多,但是具体多了什么并没有明确表达出来,相当于是一种implicit delta(隐式差量)。这个隐式的差量被固化在子类的实现中,无法独立管理和复用,这正是继承产生脆性、导致白盒耦合的数学根源。
125+
126+
这个数学表达式不仅揭示了继承的核心机制,更为我们理解面向对象编程的三大特性——封装、继承、多态——提供了统一的逻辑视角。
127+
128+
### 继承、多态与封装的统一逻辑视角
129+
130+
从更本质的视角看,面向对象常说的三大特性——封装、继承、多态——其核心目的都可以统一到 `A > B ⇒ P(B) → P(A)` 这一逻辑关系中。
131+
132+
#### 1. 继承:构建逻辑蕴含的"关系前提"
133+
134+
继承的核心价值,是为`A > B ⇒ P(B) → P(A)`提供**可定义、可传递的类型偏序关系**,它是整个逻辑链的"起点"。
135+
136+
**继承的本质是"接口契约的传递",而非"实现细节的复制"**。若仅将继承用作"复用父类私有字段/protected方法"的手段(即"实现继承"),则会破坏`A > B`的纯粹性:子类会依赖父类的内部实现,导致`A``B`的关系从"接口兼容"退化为"白盒耦合",最终为`P(B) → P(A)`的失效埋下隐患(这也是"谨慎使用继承"的核心原因)。
137+
138+
#### 2. 多态:将逻辑蕴含转化为"可执行机制"
139+
140+
多态的核心价值,是让`P(B) → P(A)`这一静态逻辑推论,在**运行时动态生效**——它是逻辑链的"执行层",也是OOP实现"灵活扩展"的关键。
141+
142+
若没有多态,`P(B) → P(A)`只能停留在"编译期的静态断言"(如"用B类型的变量调用方法,只能执行B的实现"),无法适配"子类特化行为"的需求。而多态通过两种核心形式,让逻辑推论落地:
143+
144+
1. **子类型多态(Subtype Polymorphism)**:这是OOP最核心的多态形式。当我们用基类B的引用指向子类A的实例(如`B obj = new A()`),调用`obj.method()`时,运行时会自动执行A的`method()`实现——但这一过程始终严格遵循`P(B) → P(A)`的约束:
145+
- A的`method()`必须与B的`method()`保持接口一致(参数、返回值、异常契约),否则编译不通过;
146+
- 调用`obj.method()`的代码(即`P(B)`)无需修改,就能安全适用于A的实例(即`P(A)`成立)。
147+
例如:用`Animal obj = new Dog()`调用`obj.makeSound()`,执行的是`Dog`的"汪汪叫",但调用逻辑完全依赖`Animal`的接口,符合"对Animal的操作可安全用于Dog"的推论。
148+
149+
2. **参数多态(Parametric Polymorphism,如泛型)**:它进一步扩展了`P(B) → P(A)`的适用范围。通过`List<T>`这类泛型定义,`P(List<T>)`(如"向列表添加元素")的操作可安全适用于`List<String>``List<Dog>`等任何特化类型——本质是将"类型偏序"从"类继承"扩展到"泛型参数",让逻辑蕴含式具备更强的通用性。
150+
151+
简言之,多态的本质是"**在不破坏接口契约的前提下,允许子类替换父类的实现**"。若脱离`P(B) → P(A)`的约束(如子类重写方法时改变接口契约),多态就会退化为"不可预测的行为切换",导致代码逻辑混乱。
152+
153+
#### 3. 封装:守护逻辑蕴含的"数学严格性"
154+
155+
封装的核心价值,是通过"隐藏内部实现、暴露稳定接口",**隔绝外部代码对类型内部状态的依赖**,从而确保`P(B) → P(A)`的推论不被"信息泄露"破坏——它是逻辑链的"保障层"。
156+
157+
为什么封装是必要的?因为`P(B) → P(A)`的成立,依赖一个关键前提:**外部对类型的操作P,仅依赖其公共接口,而非内部实现**。若没有封装,外部代码可能会直接访问类型的私有状态(如通过反射修改私有字段),或依赖父类的`protected`成员(如子类直接操作父类的`protected int count`),这会导致两个致命问题:
158+
159+
1. **父类实现变更会破坏子类**:若父类B将`count`改为`long total`,依赖`count`的子类A会直接失效——此时`A > B`的关系因"实现耦合"被破坏,`P(B) → P(A)`自然不再成立;
160+
2. **外部操作突破接口契约**:若外部代码直接修改B的私有状态(如跳过`setCount()`方法直接改`count`),会导致B的内部逻辑不一致(如`count`与其他状态不同步),此时"针对B的操作P"本身已不合法,更无法保证对A的适用性。
161+
162+
封装通过以下机制守护逻辑严格性:
163+
- **访问控制**:用`private`隐藏内部状态与实现细节,用`public`暴露稳定的接口(如`getCount()``setCount()`),强制外部操作只能通过接口进行;
164+
- **接口稳定性**:一旦公共接口确定,内部实现可自由迭代(如B的`setCount()`从"直接赋值"改为"加校验逻辑"),但接口契约不变——这确保`P(B)`的操作始终合法,`P(B) → P(A)`的推论也随之稳定;
165+
- **解耦实现依赖**:子类A若仅依赖B的公共接口(而非`protected`成员),则B的内部修改不会影响A,`A > B`的关系始终保持"接口兼容"的纯粹性。
166+
167+
#### 4. 三者的协同:从"孤立特性"到"统一逻辑闭环"
168+
169+
封装、继承、多态并非三个独立的"技巧",而是围绕`A > B ⇒ P(B) → P(A)`形成的**逻辑闭环**
170+
1. 继承定义"`A > B`的偏序关系",为逻辑推论提供"关系基础";
171+
2. 封装确保"操作P仅依赖接口",为逻辑推论提供"可靠性保障";
172+
3. 多态实现"`P(B) → P(A)`的动态执行",让逻辑推论落地为"可扩展的代码"。
173+
174+
任何一环的缺失或滥用,都会破坏整个闭环:
175+
-**滥用继承**(如为复用实现而继承,违反LSP):`A > B`的关系从"接口兼容"变为"实现耦合",`P(B) → P(A)`的推论会因父类修改而失效;
176+
-**封装不足**(如过度暴露`protected`成员、用public修饰内部状态):外部操作会依赖实现细节,`P(B)`的合法性不再稳定,`P(B) → P(A)`失去严谨性;
177+
-**多态脱离契约**(如子类重写方法时破坏接口):多态会变成"行为混乱的切换",`P(B)`的操作无法安全适用于A,逻辑推论彻底失效。
178+
179+
#### 结论:OOP三大特性的本质是"构建可推理的类型系统"
180+
181+
我们常说"OOP是对现实世界的抽象",但更深层的本质是:OOP通过封装、继承、多态,构建了一套**基于逻辑蕴含的"可推理类型系统"**
182+
183+
这套系统的核心目标,是让开发者能基于"类型关系"(`A > B`)预测代码行为(`P(B) → P(A)`),从而降低复杂系统的认知负荷——当我们调用`process(B obj)`时,无需关心`obj`是B还是其子类A,只需知道"对B合法的操作对A也合法",这便是OOP能支撑大规模软件开发的根本原因。
184+
185+
虽然继承范式在理论上有其严谨性,但正如我们所见,这种`A > B ⇒ P(B) → P(A)`的断言式逻辑在实践中面临着根本性的挑战。现在让我们转向组合范式,看看`A = B + C`的代数构造如何提供更优的解决方案。
186+
121187
### 组合范式:代数构造与模块化构建
122188

123189
与继承的断言式逻辑截然不同,组合的核心由公式 `A = B + C` 定义。
124190

125191
这是一种**构造式**的逻辑范式。它不做模糊的"是"之断言,而是精确描述类型 `A` 的构成:`A` 是由组件 `B``C` 通过代数运算"组合"而成。此处的 `+` 是抽象代数运算符,可表现为聚合、依赖、委托等具体关系。
126192

127-
这种构造逻辑为软件系统带来了坚实的优势:
193+
`A = B + C`不仅明确表达了A比B多,而且多出来的部分被明确表达为可复用的组件C,相当于是一种explicit delta(显式差量)。
194+
195+
这种将差量显式化、组件化的构造逻辑为软件系统带来了坚实的优势:
128196

129197
1. **松耦合与黑盒复用**`A` 仅依赖于 `B``C` 的公共接口,对其内部实现一无所知。只要接口契约不变,组件可以独立替换升级,系统保持稳定。
130198

@@ -136,7 +204,7 @@ superHero.learnAbility(new InvisibleAbility());
136204

137205
如果说"组合优于继承"指明了软件结构演化的方向,那么 **Trait 机制**(特质/特征)就是这一方向在编程语言设计中的具体体现。Scala、Rust 等语言的 Trait 系统不仅解决了传统继承的结构缺陷,更从语言层面确立了"**差量可独立存在、可自由组合**"的构造范式。
138206

139-
传统继承中,`class B extends A` 隐含了一个不可分割的整体:B 的增量行为被绑定在 A 之上。而 Trait 将这个增量显式封装为独立的结构单元
207+
传统继承中,`class B extends A` 隐含了一个不可分割的整体:B 的增量行为被绑定在 A 之上。而 Trait 将这个增量**显式封装为独立的结构单元**,也就是我们前面提到的 explicit delta
140208

141209
```scala
142210
trait HasRefId {
@@ -187,9 +255,18 @@ App = Generator<DSL> ⊕ Δ
187255
- **Kustomize**`最终配置 = 基础配置 ⊕ 环境差量`,通过补丁实现配置的可逆变换
188256
- **前端框架**`ΔVDOM = render(NewState) - render(OldState)`,虚拟DOM差分算法本质上是可逆计算
189257

190-
可逆计算理论揭示的核心洞察是:**完整的变化描述必须同时包含增与减,这对应于差量中必须同时包含正元素和逆元素**。这种数学完整性使得软件演化变得可预测、可管理。
258+
可逆计算理论揭示的核心洞察是:完整的变化描述必须同时包含增与减,这对应于差量中必须同时包含正元素和逆元素。这种数学完整性使得软件演化变得可预测、可管理。这不仅印证了从组合与代数构造出发这一思路的正确性,更将我们引向了基于第一性原理构建软件的理论道路。
259+
260+
关于可逆计算理论的详细介绍,可以参见如下文档:
191261

192-
可逆计算理论的发展验证了我们方向的正确性:从组合的基本思想出发,沿着代数构造的路径深入探索,我们能够建立起更加坚实、更加普适的软件理论 foundation。
262+
## 参考文档
263+
- [可逆计算:下一代软件构造理论](https://mp.weixin.qq.com/s/CwCQgYqQZxYmlZcfXEWlgA):对可逆计算理论的概要介绍,阐述了其基本原理、核心公式,以及与图灵机、Lambda演算这两种传统计算世界观的区别。
264+
- [DDD本质论之理论篇](https://mp.weixin.qq.com/s/xao9AKlOST0d97ztuU3z9Q): 结合(广义)可逆计算理论,从哲学、数学到工程层面,系统性地剖析了DDD(领域驱动设计)的技术内核,认为其有效性背后存在着数学必然性。
265+
- [DDD本质论之实践篇](https://mp.weixin.qq.com/s/FsrWW6kmOWHO0hQOS2Wj8g):作为理论篇的续篇,重点介绍了Nop平台如何将可逆计算理论应用于DDD的工程实践,将DDD的战略与战术设计有效地落实到代码和架构中,从而降低实践门槛。
266+
- [DDD本质认知的演进:从实践框架到构造理论](https://mp.weixin.qq.com/s/6bONsaTE79shhSHfrKiyMw): 通过AI辅助的思想实验,对比了传统的DDD概念框架与《DDD本质论》中从第一性原理(空间、时间、坐标系、差量)出发的推导路径,揭示了后者更深刻的内在逻辑。
267+
- [广义可逆计算: 一个软件构造范式的正名与阐释](https://mp.weixin.qq.com/s/pNXPEvyVB7ljOhBQVh6c-A):为“广义可逆计算”(GRC)正名,阐释了其核心思想——以“差量”(Delta)为第一类公民,系统性地管理软件构造过程中的可逆性与不可逆性,旨在解决“复杂性”这一核心工程难题。
268+
- [从可逆计算看Delta Oriented Programming](https://mp.weixin.qq.com/s/XQlzQSGo-gqColvDw7UPyA):对比了可逆计算与学术界的面向特征编程(FOP)和面向差量编程(DOP)等理论,指出可逆计算通过引入“场”和“坐标系”的观念,能更有效地管理“预料之外的变化”。
269+
- [软件构造的新物理学: Gemini AI对(广义)可逆计算理论的深度报告](https://mp.weixin.qq.com/s/pca_qmmygSNyEpqJjLLSPg):记录了AI在人类精心设计的引导下,如何通过结构化的学习路径(搭骨架 -> 深度学习 -> 交叉验证),自主构建起对(广义)可逆计算理论的宏大逻辑框架。可以作为可逆计算理论系列文章的导读。
193270

194271
## 结论:从分类学到结构学的思维转变
195272

0 commit comments

Comments
 (0)