
是否有人想过,“顺序”是代码非本质复杂性的根源。
“顺序”是双刃剑,代码量少时方便,一旦程序变大,就会变为“枷锁”,改动一点儿都可能崩塌,而需求变化却是常态。
真相是,不按照顺序,我们依然可以把逻辑正确描述出来。因为逻辑关系自带方向性,可以自动推导。真正适合顺序的地方是计算过程,而非逻辑。
打破“顺序枷锁”,才能从根本上提升代码的稳定性和可维护性,不再需要重构。因为“稳定性”,本就不该依赖于天生脆弱的顺序。
https://github.com/rainforesters/imsure
github.com/rainforesters/imsure // [编译期间] // 定义规则,描述依赖关系,与顺序无关 A = X + Y Y = D - E X = B * C // [运行期间] // 可以在任何位置、任何时间进行赋值 E = 1 // wait 1s C = 2 // wait 1s B = 3 // wait 1s D = 4 // wait 1s (A: 9, Y: 3, X: 6) 1 w568w 35 天前 |
2 Leviathann 35 天前 何意味 |
4 chendy 35 天前 字文的序顺不影响阅读是吧 道理我都懂,但是乱序执行不是编译器和运行时的事么 普通人类乱序写代码是想训练 AI 么 |
5 laminux29 35 天前 |
6 adoal 35 天前 并没有什么非得按顺序写代码。从上层来说,有纯函数式程序设计等范式。从底层来说,有 CPU 乱序执行。只是你不关注罢了。 |
7 Rickkkkkkk 35 天前 这就好像你在 21 世纪,去重新研究 18 世纪前人就搞完的数学一样。 要不先上个大学? |
8 vfs 35 天前 所以你的项目解决了什么问题? 我要如何使用你的项目? |
9 dog82 35 天前 可以,但是会影响编译速度 |
10 muchan92 OP 这是解决数学或乱序执行问题吗?请先搞清楚再说好吧。 |
11 Alias4ck 35 天前 goto |
12 muchan92 OP @vfs 使用声明式写法,用规则来描述业务逻辑。就像写方程式一样,业务逻辑直接映射为规则,不需要推导,它会自动按正确顺序执行。即使需求变更,也只是调整下规则的依赖关系而已,简单可靠,不会涉及到推翻脆弱的代码顺序。 |
13 villivateur 35 天前 您是否在找:HDL |
15 NewYear 35 天前 我同意楼主的想法,且感同身受。 我会写程序,当我成为领导后,再也不关心所谓的顺序写代码。。。 我乱序的把指令丢给下属。。他会自动的把我的想法用代码描述。。。并自动放在指定的位置。 乱序编程法,并没有任何问题。 你只是需要一个中间件,哪怕这个中间件是“人”。 |
17 OneLiteCore 35 天前 代码是给机器执行的没错问题是代码也要让人读让人来维护,搞乱顺序或者额外定义一套依赖关系并不会对生产力有任何提升,但是带来的维护问题却是无法忽视的。 本来大公司的代码就已经是一座屎山了各个年代的代码各种设计模式和写法都有,加上这套玩意不如直接在招聘简章里面要求必须剃光头了。 |
18 CodeCodeStudy 35 天前 编译器会重排序的 |
19 muchan92 OP @villivateur 是 Hardware Description Language 吗?挺好玩,有意思。 |
20 deplives 35 天前 请让我尊称您为计算机民间科学家 |
21 BestPix 35 天前 你可以设计一个乱序输入的编辑器,不要顺序打字。 |
22 Gilfoyle26 35 天前 |
23 muchan92 OP @OneLiteCore 为什么会错误的以为这会更难维护?实际上这更容易维护。你以为你需要弄懂所有的规则才能写代码、改代码?并非如此,你甚至不需要感知它之前是否有规则,你只需要描述你的规则就好了。就像类型约束一样,假设一个类型为 int64 的变量,它的取值范围从无规则时 64 位,到规则 1 约束 32 位,再到规则 2 约束 16 位。 |
24 Ketteiron 35 天前 好奇看了下 demo 给我看晕了。 这要是真有人用在生产上,怕是一半时间都在 debug 。 声明式/响应式编程我承认有一定合理性和可行性,本质上是希望将 n的组合复杂度缩小为 2n ,虽然其实并没有消除任何复杂度。 |
25 muchan92 OP @Ketteiron 思维惯性的阻力,你若看 prolog 的话会更晕。和上条回复一样,错觉以为这会导致更难 debug ,实际上你几乎不需要 debug 。因为,若定义一条规则把取值范围从 64 位收窄为 16 位,那么它一定会收窄为 16 位,这是确定的肯定不会出错。同理,假设有多条业务规则作用于一个变量上,那么它也是取值收窄的过程,并且每次都是确定的不会出错,由此推及整个程序也是确定的。所以,实际上很少需要 debug 。 |
26 liuchenx 35 天前 1. 你这解决了什么问题? 2. 有什么优势? 就目前发的那个 demo 看不出来什么,连个业务相关的 demo 都没有, 一上来就各种付费,你觉得这里的人谁会上当? |
27 YUX PRO zig |
28 lqs 35 天前 您是否在找:Microsoft Excel |
29 maigebaoer 35 天前 via Android Excel 满足你 |
30 muchan92 OP @liuchenx 有示例 https://github.com/rainforesters/imsure-demo ,按照惯性思维,你可能会觉得难看懂,但要实现相同功能,按传统方式来写代码肯定会复杂得多。你最好先忘掉规则,只把数据结构当做一个普通对象,读写任何属性都是正确的。然后再去看,规则是如何保证属性始终保持正确性的。 |
31 shyling 35 天前 因为高级编程语言讲究的就是按人脑思维。 机器确实不那么 care 顺序,所以这是编译时运行时的优化点。 |
32 muchan92 OP |
33 afirefish 35 天前 上层:依赖倒置,切片编程等都是系统性解决代码可维护性的东西,或许就是你说的非顺序执行? 下层:微处理器乱序执行(虽然我讲不出原理,但是我知道有这么个东西) |
35 forisra 35 天前 这是特德姜《你一生的故事》(也就是电影《降临》)里面的七肢桶来地球了?要用非线性语言来给我们使用线性语言的人类大脑升级一下。 |
36 pweng286 35 天前 我怎么记得好像刷到过 |
38 henix 34 天前 我很喜欢 Makefile ,以前也思考过能否将 Makefile 式的依赖计算引入到编程语言内部 一个看起来很接近的东西是 Vue 的 Computed Properties ,个人认为在某些场景下还是有用的,比如能自动缓存 但大多数情况下直接用变量赋值确实是最简单的 |
39 kome 34 天前 via iPhone 处理器: 我不造啊,我要计算 a-b ,但是 ab 的数据还没送过来呀,c+d 的数据已经送过来了,反正闲着也是闲着,我就先计算 c+d 了。 |
40 340244120w 34 天前 预告后续楼主总篇: 《如何让同事懵逼,让领导抓心:构建代码护城河完全指南》 |
41 muchan92 OP @340244120w 你认为这会抬高编程门槛?相反这其实会降低编程门槛。我们十几个项目都工作良好,稳定可靠。 传统思维会认为,在没有完全弄懂程序的所有细节之前是不可能正确修改代码的,因为每一行代码都堆叠在前面的代码之上,移动一点儿都可能崩塌。 但这种方式不会。你完全不必了解全部规则,也能放心大胆地修改代码,不会出错。为什么呢?举例说明,假设需求变了,要把程序改为 A = X + Z 。你有两个选择: 一、你开心时,可以找到 A = X + Y 的地方把 Y 换为 Z 就好了; 二、你不开心时,忘掉之前的 A = X + Y ,管那么多干啥,直接新写一个规则 A = X + Z 把之前所有关于 A 的覆盖掉就好了。 现在你不必了解全局也可以放心大胆地写代码了。 因为每一个规则,只关注依赖的变量,但不必关心被依赖的变量在哪儿、何时准备好,仅仅把自己计算正确就行了。当然,被依赖的变量也是如此计算的。 所以,从方法二可以看出,即使程序迭代了上百次,你也可以完全忽略已有规则,就当它们都不存在,所有变量都是新的,大不了就把新需求从头写一下而已。 |
42 Tink PRO 我看不懂你说的,有实际应用?发个大型一点的 demo 出来看看 |
43 msg7086 34 天前 我怎么感觉类似的东西我大学里写 haskell 的时候就写过了。 |
44 canteon 34 天前 你快乐就行 |
45 xtreme1 34 天前 来碰瓷 pl 领域了, 开始发明 theorem prover 了? Coq / Agda 了解一下先 |
46 cocong 34 天前 思路听新奇,不过思想上只是一个框架,为何不直接开发一门新的编程语言,那样用起来应该会更简单 |
47 cocong 34 天前 思路很新奇,不过实现上只是一个框架,为何不直接开发一门新的编程语言,那样用起来应该会更简单 |
48 cmos 34 天前 1. 乱序早几十年就有了。 2. 至于“语言”的顺序,是为了让人更好的写、读、理解。 3. 楼主本科哪个学校的?可曾读过什么书? 4. 一眼就是民科。尤其是这种代码,居然用 js 演示,明显的不是科班出身,至少不懂组成原理和结构。 |
49 phcbest 34 天前 程序员里面的常熟阿诺 |
50 roykingH 34 天前 代码是给人看 不是给机器看的 编译器会优化 你写的顺序未必是机器执行的顺序 有时间可以看看编译以后的代码长啥样 |
51 rb6221 34 天前 额,我就说一个点,如果你觉得你写的东西真的很复杂,能不能像研究生那样写一个详实的几万字论文出来,而不是在帖子里对着回复者说“你不懂,但是我懒得跟你解释,懂的人自然会懂” 你这样真的是在推广你的理论吗? |
53 muchan92 OP |
54 visper 34 天前 haskell 之类的极端纯函数式编程?全部都是函数定义,最后由一个函数出结果。 |
55 muchan92 OP |
56 chairuosen 34 天前 “有一部分变量关系声明不需要顺序” 等于 “编程不需要顺序” ? 先关闭冰箱门,再塞进大象,再打开冰箱门? |
57 OneLiteCore 34 天前 @muchan92 这不是 “错误的以为” 而是行业目前的现状,是经受了数十年全球大规模应用部署和验证过的,你应该也知道目前你描述的这种方法并不是被普遍接受的主流对吧。 项目内业务是会互相耦合的,可能就是你说的逻辑关系或者依赖关系,是这个关系其存在本身错综复杂导致的稳定性和可维护性问题,与是否顺序无关。 |
59 OneLiteCore 34 天前 另外程序执行必定会先有一个起点然后再有一个终点,这注定在时间上是存在线性的顺序关系的,电脑高低要先开机才能关机而无法反过来对吧。 |
62 xtreme1 34 天前 @muchan92 #53 我们要解决的问题是维护程序的正确性. 大部分现代程序采用的方式是上 unit test, regression test, 上静态分析 另一条路是写出符合某 specification 的代码, 即 formal verification, 也是你实际上在做的路子. 这是 cs 中 pl 领域的很大一块, low hanging fruit 基本不存在了. 想入门这块可以从 Software Founditions 和 PLFA 看起. 所以 #1 说你是计算机民科是毫不夸张的. |
63 fregie 34 天前 我觉得你这玩意的终点是 FLUX 架构:单项数据流,声明式编程 |
64 cenbiq 34 天前 看了一下你这个项目,似乎是受到 vue 观察机制或者 rxjs 的启发,相当于一个完全使用响应式数据流驱动的概念,但问题是我直接写 vue 全用计算属性,或者直接使用 angular 不好吗?而且你得思考一个问题,所有业务都适合响应式数据流吗?我以前用 angular 时思考过这个问题,个人认为大多数业务不需要使用数据流来处理。 |
66 sir283 34 天前 我怎么就想不到这种水贴的方式啊,难怪我的币还是这么少。 |
67 cenbiq 34 天前 而且你这个所谓“乱序”也就是声明式数据流,复杂度一旦高起来调试会非常困难,我写过数据处理流程相当复杂的 android 项目,完全使用 kotlin Coroutines/Flow ,并且存在一些过度使用 flow 的情况,你知道对复杂的数据流进行调试和不小心搞出来的数据流循环的调试有多麻烦吗? |
68 muchan92 OP @OneLiteCore 首先抱歉,我不应该用“错误”而改用“错觉”更合适,后面一条回复就使用了“错觉”。 其次,你所讲的是业务需求的本质复杂性,它不会被消除,但使用命令式写法会引入更多的非本质复杂性。正如 #41 举例,若按照命令式写法,你首先得在计算 A 之前,先计算出新的 Z ,而 Z 有可能是异步的,所以不得不重新打乱之前已有的同步计算 A 的过程,重构代码。而这种方式则不会,修改局部即只作用于局部。程序维护一次和维护一百次时维护难度是相同的。 |
69 Mark24 34 天前 类似 Mobx 把 React/Vue 的 响应式 带到 写逻辑中。 一种发布订阅模型的应用 |
70 unused 34 天前 第一步:1+1=2 第二步:付费 内容没看懂,来个斐波那契数列看看? |
71 muchan92 OP @cenbiq 你的几个举例,并非完全“声明式”,它们调试难度就是为了抵消“非完全声明式“所引入的额外难度。递归和循环问题我都遇到过,程序会第一时间指出该问题,不会隐瞒。 |
72 Ketteiron 34 天前 @muchan92 #68 缺点是几乎无法正常测试,所有规则都是黑盒,就如#62 说的,可维护性是非常重要的,能保证大型项目能正常迭代。 你这种做法相当于是放弃了各种测试和静态分析,在组合数量爆炸时虽然不用梳理大量组合逻辑,但是一个规则对其他规则以及集合总体的影响是几乎无法预知的,有好处,也有坏处,在我看来坏处大于好处。 |
73 docx 34 天前 via iPhone 顺序对机器不太重要,但如果人工要介入 debug 什么的就有得受了 |
74 gaobing 34 天前 狭隘了 老弟 要我说 你还得多学学 你说的顺序 只是上下行间的顺序 那你有没有想过 为什么按照要从左到右的拼写顺序写代码? 为什么要横着写代码? 难道代码天生就该依赖 脆弱的左右拼写顺序和横行顺序? 我给你演示下什么是好代码。 打破从左到右的顺序: // int a; a tni; // if (condition) { noitidnoc fi { // doSomething(); gnihtemoS od; // } } 打破横行的顺序,竖着写代码: i i n f t ( c a o = n 1 d ; i t i o n { } 打破所有顺序,天生强壮的代码: ifit}a ={1oc ond ition doS ohi ngmet |
75 muchan92 OP @docx 实际上 debug 没有想象中那么难,因为若一个值是错误的话,那么它不会传播很远,可能下一个就定位到了。所以,错误不会如想象中那般,传播得非常遥远。 |
78 nickyadance23 34 天前 太好了,我们发现了计算机的终极 |
79 geminikingfall 34 天前 @w568w 填补了知乎上说计算机没有民科的空白。 |
80 shouh 34 天前 顺序是让自己看得懂而已 |
81 kome 34 天前 via iPhone [编译期间] def add(x:int,y:int): return x+y [执行期间] x=1 y=2 println(add(x,y)) 顺序重不重要?当然重要,不给能源,处理器就无法工作,至于你给处理器什么电路,什么功能,这些在有没有能源面前,屁都不算。 |
82 expy 34 天前 SQL 了解一下,只管声明想要的结果。 |
83 yxc246800 34 天前 你认为的顺序只是你的逻辑方式是顺序的,所以写出来的代码是顺序的。 至于编译器,链接器,执行器如何理解你的代码那就不一定是顺序的了,你理解还只在表面。 高级语言就是服务于生产者的,如果顺序逻辑是有利于生产者生产的那就是顺序逻辑最合适。 所以并非是写代码的人选择了顺序写代码,而是代码本身在最表层选择了顺序逻辑 |
84 IndexOutOfBounds 34 天前 |
85 dlyxy 34 天前 "wait 1s"是什么意思,不要性能了? |
86 lscho 34 天前 代码顺序只是解决人类读写问题而已,运行期间又不是按照代码顺序来的 如果你想反驳没必要顺序,那你为什么在这里回答别人是按顺序来的呢? |
87 cnhongwei 34 天前 这样的代码,不说好不好看懂,就说,如果变量一多,规则一多,出现循环依赖如何调试?如果有一些数据是与时间等外部相关的数据,怎么稳定? |
88 zacard 34 天前 damn !我怎么就想不出这种忽悠付费的方式 |
89 felixcode 34 天前 你先出个编译器或解释器吧,别在这大套的理论,说的越多越民科 |
90 muchan92 OP |
91 muchan92 OP @IndexOutOfBounds 解释的可以。它是通用编程,没有场景限制,非要说的话,就是写小一点的项目或脚本用命令式方法更简单,中大一些的项目我就会用这种声明式写法。 |
92 v2er119 34 天前 支持一下 OP ,JS 水平比我高,还有开源精神。 |
93 unclejimao 34 天前 @w568w 啊,有一种被剧透的感觉,你坏坏 |
94 shaozelin030405 34 天前 那整体逻辑支持交换律吗 |
95 intmax2147483647 34 天前 哈哈哈哈 这玩意儿能要付费也太离谱了,至少把 README 写完整一点让人知道你的卖点是啥吧 |
96 kome 34 天前 via iPhone @muchan92 你说的这东西不就是函数定义么,定义好了扔那就是了,数据啥时候需要处理,啥时候去找函数就是了。不需要了扔,随你删不删;需要修改了,可以修改函数本身,也可以去重新定义一个新的。 |
97 jy02534655 34 天前 |
98 Terry05 33 天前 代码是写给人看的,很多时候代码的重构就是为了增加可读性 |
99 qgmzmy 33 天前 via iPhone 何意味 |
100 levelworm 33 天前 你可以不断地 goto 啊?以前写 BASIC 代码就是这样,跳来跳去的,一会自己都晕了。C 也是可以的。 |