人心中的成见是一座大山,数据转换思想

67 天前
 muchan92

https://github.com/rainforesters/imsure 一直在用,确实好用,已经离不开了

https://github.com/rainforesters/imsure-demo

上周发了一个主题后评论区颇为热闹,就用此文统一回复下吧。我不想争论是非,只是我觉得这个理论就像日心说一样值得被更多人知道,应该被更多人知道,哪怕它和日心说一样被证明是错的,也算挣脱了思维桎梏,启迪了方向。若值得在茶饭之余引发讨论就更好了。


程序的本质是数据转换,那么逻辑过程的意义可以一概视为根据 input 转换为 output ,所以我们可以试着改变一下程序的编写方式,

从:

f(input) ⇒ output

进化为:

output ⇐ Watch_transform(input)
Rule = Watch_transform
output ⇐ Rule(input)

为了让观察转换变得可行,我们把 input output 作为字段都定义在抽象的 Struct 类型上,

那么就得到了:

self.output ⇐ Rule(Struct.input)
self 是 Struct 的实例
Rule 就可以在 self 未实例化之前,提前定义在抽象的 Struct 类型上;同时也允许 input output 在 Struct 的不同层级

这就变为了纯粹的数据转换链。只要依赖的 input 更新 output 也会随之更新,整条链也随之更新到最终稳定状态,既简单又保证了确定性。在转换链中,每个节点只干一件事,只需观察依赖的前置数据而不必考虑后续自己会驱动谁或被谁所依赖,彻底摆脱逻辑控制流。

这种写法就像从算术方法到方程解法一样具有普适性。
从传统编程需要根据不同业务需求设计不同的实现过程,到全然不用设计,只套用一条普适的方法就行:

  1. 定义数据结构。(设未知数)
  2. 定义转换规则。(列方程式)
  3. 为字段赋值。(代入已知数)

至此,就再也不需要推导业务逻辑了。


若你看懂了以上内容,那这段自不必说,若没看懂请继续。

传统逻辑过程可以细分为两部分:

  1. 先把将要进行转换的 input output 建立关联。
  2. 然后进行转换,纯粹的转换算法。

传统写法下 80% - 90% 的代码都在建立关联、维护关联,其实转换算法的代码很少很少。
新写法中建立关联就像呼吸一样简单。

7893 次点击
所在节点    程序员
56 条回复
liprais
67 天前
"告别不会写,菜鸟变老鸟,老鸟变鲲鹏,自己写的代码一定是对的,没有 bug 。"
拉黑不送
nuk
67 天前
感觉像程序逻辑之外再隐藏一个巨大的状态机,属于那种加一行炸了死活找不到原因的。
NessajCN
67 天前
找韭菜不建议来这里找,
作为卖课人首先要学会找准潜在目标客户。
JIlIlIlIl
67 天前
什么东西?对面向对象概念有了解的,或者懂些 DDD 的 coder ,会同意你拿这些皮毛来割韭菜吗?
建议大家看看什么才是真正的知识分享: https://docs.mryqr.com/build-your-own-software-skyscraper/
ZiChun
67 天前
引用一下你的发言:
```
这个理论就像日心说一样值得被更多人知道,应该被更多人知道,哪怕它和日心说一样被证明是错的,也算挣脱了思维桎梏,启迪了方向
```
感觉可以了解一下 邓宁-克鲁格效应。
wang93wei
67 天前
如果都按照这个思想去训练大模型,你猜会出来什么。
czfy
67 天前
你说的这些在学术领域专门用来做数据分析、不放生产环境的语言里并不少见,例如 R
但结论就是业界基本没人用
shadowyue
67 天前
你这个有没有应用到复杂度高一点的实际项目中的例子
nightlight9
67 天前
说实话,我没看懂

看到了数据转换,难道是 rjava 那种数据驱动的思想?
ZiChun
67 天前
怕你不服气,我抽了点时间看了看这个的几页介绍才来回复的。
首先,这种方式并没有真正消除逻辑复杂性,而是将其分散到各个独立的 ruledef 里。debug 的时候就知道什么是 callback hell 了。
然后,对于需要显式控制执行顺序、循环次数、中断条件等的场景,用这个方式反而是徒增思考成本。
还有,用 setTimeout 解决递归问题的行为,太变态了无法评价。

我举两个例子:
dijkstra 算法和需要 rollback 的时候,用你这个所谓的“挣脱了思维桎梏,启迪了方向”的编程思想,都是依托答辩。
mikaotaku
67 天前
函数式编程?
andyskaura
67 天前
@ZiChun #10 我也是看到那句“巧妙地借助 setTimeout 来放空当前堆栈,在下一个调用帧来修正自己”,大为震撼,不能说这里有什么 bug ,但根据经验来看,这地方铁定有坑,而且很难排查。
Blanke
67 天前
忍不住回复下,看到这里大为震撼,缓缓打出一个?

`由于结构体都是开放的、纯粹的,所以无法在赋值时进行拦截。不过我们可以通过定义一个规则来观察某个字段并修正自己。这就导致了递归,因为递归可能会导致堆栈溢出,所以我们巧妙地借助 setTimeout 来放空当前堆栈,在下一个调用帧来修正自己。`
liu731
67 天前
写的什么八股文,代码是给人看的
Erroad
67 天前
鉴定为魔道学者
wyntalgeer
67 天前
我学不学无所谓,面向对象必须死!
muchan92
67 天前
@ZiChun 本不想评论,但既然都在说递归,那么就简单解释一下吧,禁用递归是刻意为之,而不是不能实现,允许递归其实更容易实现。那么禁用递归的主要原因是:1. 在没有状态机堆栈结构的前提下,是难以实现尾递归的,那么就有可能导致宿主语言堆栈溢出,是有可能而不是必定; 2. 禁用递归采用变通方式不会影响代码功能,反而能让开发者明确知晓此处会产生递归,能有效防止意外情况,权衡之后因而采用。关于后面两个例子,dijkstra 是算法问题,函数更实用,不必强用这种写法来实现,这种写法更适合解决实际中的业务内容。rollback 就更简单了,字段状态重设就好了。
rarpainting
67 天前
我就这么说吧,你这只是把高级语言的关键字改成符号而已,和什么转换思想没什么关系,简单例子是个封装器,但是一旦到复杂操作就又变回面向过程了...
macaodoll
67 天前
若你看懂,自不必说........纯纯搞心态的句式.............
mynameislihua
67 天前
无聊,浪费时间

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://yangjunhui.monster/t/1122487

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX