当前位置: 华文问答 > 数码

编程真的能改变人的思维方式吗?

2016-12-12数码

与其说「编程改变人的思维方式」,不如说是「思维方式合适的人在这个行业更能如鱼得水」;然后再被工作环境以及团队中的同类反复强化,越发显示出其独特性来。

程序员思维第一个,也是最显著最根源的特征是: 一切程序员都是还原论者

没错,你完全可以说,「等等!我是程序员,但还原论是啥啊?」

嗯,你可以不知道什么是还原论,但你仍然是个还原论者。

所谓还原论,指的是「世界一切复杂事物都可以约分到一系列较为简单的子系统、再由简单子系统约分到很少几个简单原理上」,并且「通过很简单的几条原理、若干子系统的组合和相互作用,就可以分毫不差的精确模拟一个复杂系统」这样一种信念。持有这种信念的,就叫还原论者。

很显然,能够计算一切可计算物的图灵机就是最最典型的还原论机器。

如果你身为程序员却不相信还原论、没有拆分复杂事物的能力,那么你一定会在这个行业活的非常非常的痛苦。

举例来说,熟练掌握还原论,学习知识你可以只学核心逻辑;一旦学会后,随便什么新技术什么新架构新原理,在你看来都是新瓶装旧酒:程序员基础掌握得好学新东西真的就快么?

类似的,熟练掌握还原论,那么一个外人看来非常非常麻烦的需求,在你看来就是一组核心计算法则(比如传统数据库的核心就是关系代数)的一系列组合而已。于是在别人看来得喀喀喀喀出苦力敲出无数行代码的东西,在你看来,只需设置很少几条「生成规则」,然后让计算机执行这些规则,一切功能便自然涌现。

典型如生命游戏(Game of Life)有哪些图形? ,简单的几条规则就能得到无穷无尽的动态花样。

当然,生命游戏只是个最简单最容易理解的例子,所以看起来毫无用处。我想说明的只是「其实程序员的工作中,需要的各种功能也可以用类似方式自动引出」——典型如现在如日中天的AI背后的神经网络。

显然,如果一个人不相信、不理解还原论,甚至连个八音盒的原理他都理解不了,那么他一定学的慢、写代码出呆力、还老是弄出一大堆bug。这种人实际上是做不了程序员的。

这个特征会在程序员和普通人的交流中造成什么影响呢?

喏,我的亲身经历:是不是真的有不适合编程的人?

普通人一般不会把「逻辑推理」当成「常规武器」使用,和程序员离开逻辑就没法说话完全不同——还原论的还原可不是「背诵很简单的几句口诀」,而是「用这几句口诀还原整个世界」。那么这逻辑推理对他们,就必须吃饭喝水一样自然。

于是,程序员和普通人说话时,很容易出现这种场景:

程序员:我都说这么明白了你还不懂吗?

普通人:这家伙为什么非要把那么简单一句话翻来覆去说那么多遍?!我早懂了能不能别说了咱换下个话题好不好?

比如我提到的那名女生,她很明显就对「计算机会把你写在文本里的指令按从上到下的顺序一条条执行一遍」毫无感觉。这句话太浅,所以呢?下一个需要我记忆的知识点是什么?

但对程序员来说,这句话等于开天辟地懂吗!

最简单的,你们班有50个人,要把他们的名字每人一行的打印出来;而putchar一次只能打印一个字符,怎么办?

简单,按顺序putchar("李")然后putchar("四")再putchar一个回车,这不就是「一行一个名字」吗?

对每个人名,重复这个动作50次,这不就是「五十个人的名字每人一行的打印出来」吗?

「重复执行动作」被计算机语言专门支持,叫循环语句;那么安排好循环,把人名一个个「喂」给这个东西,那么顶多十行代码,这个任务不就完成了吗?

你看,还原论者说出的「简单常识」「抽象理论」,默认是可以被展开被执行被任意组合的;如果你想不到「我自己可以展开/组合/执行他说的东西」,那么这些话将永不能被你理解。

我带的那名女生要做的,其实比这个更简单。但是她没有这种还原论思想,我最终也没能给她引导出这个思想。所以她学再久都学不会编程。

并不仅仅涉及编程时会出现「有无真正理解还原论」的冲突。比如谈论工程谈论机械、谈论股市谈论政策、谈论历史事件谈论文学作品……一切的一切,如果有还原论方面的理解,很容易就会「找出几条基本原则然后代入模型开始推演」——你看,还原论思维模式贯穿始终。

那么这时候,很容易出现这种情况:普通人/整体论者谈论「斯德哥尔摩综合征」的种种表现;而还原论者则力图仿照「囚徒困境」「胆小鬼博弈」构造出一个合理的博弈场景来,把「习得性无助」、「斯德哥尔摩综合征」的成因找出来。

如果不理解还原论,那么你很容易发现,程序员们总喜欢不分场合的显摆各学科的「入门知识」或者「极为抽象的怪异概念」——他们永远纠结在很「浅薄」很「抽象」很「无趣」的入门知识上,永远不肯和你正面面对「现实问题」。当你要求他们「谈论问题」时,他们甚至可能很生气的告诉你「什么都没搞懂谈什么谈」、「我们谈的就是这个问题,你确定你听懂了?」

——当然,如果你理解了我的讲解,那么你大概就会明白:哦!这就是还原论者啊!他们不喜欢那些没有由来的「高层论断」,从最简单最基础最不可能错的「基础知识」开始、自己主动构建/推导出「高级话题」,这才是他们的思维模式。

程序员思维的第二个特点是系统论。

系统论(科学名词)_百度百科

系统论是研究系统的结构、特点、行为、动态、原则、规律以及系统间的联系,并对其功能进行数学描述的新兴学科。系统论的基本思想是把研究和处理的对象看作一个整体系统来对待。系统论的主要任务就是以系统为对象,从整体出发来研究系统整体和组成系统整体各要素的相互关系,从本质上说明其结构、功能、行为和动态,以把握系统整体,达到最优的目标。

如果是还原论是拆解,那么系统论就是组装——我猜很多哲学爱好者在看到我说程序员都是还原论者时,已经对他们有了一个判断……

虽然说只要不是哲学学的走火入魔了,都不会觉得「还原论者都是些只见局部不见整体的渣渣」;但其他行业的还原论者,尤其是那些更容易为公众所知的、纯科学纯数学纯技术的研究者,他们都很容易造成这样一种整体印象:所谓还原论者,就是只研究眼睛中的其中一种感光细胞里面的其中一种化学物质、其他一切他都不管的「书呆子」……

但这个判断并不全面。

软件工程毕竟是一个工程学科。光会拆,你永远都不可能拆出一辆整车来;同样的,做工程,你必须会组装——从最最基本的概念、标准化的各种零件/组件开始,设计一个合适的架构,把它们装配到一起,得到让客户满意的产品。

因此,任何合格的程序员,或多或少都有点系统论基础——模块如何划分?你打算传什么给我、能做到何种程度的保证?我需要回馈给你什么?

如果这些都理解不了……

更进一步的,怎么通过系统各部分采集的信号,设计出合适的正负反馈机制,使得软件系统可以「自适应」于工作环境?

这个东西继续发展,就是「控制论」。

控制论_百度百科

研究动物(包括人类)和机器内部的控制与通信的一般规律的学科,着重于研究过程中的数学关系。综合研究各类系统的控制、信息交换、反馈调节的科学,是跨及人类工程学、控制工程学、通讯工程学、计算机工程学、一般生理学、神经生理学、心理学、数学、逻辑学、社会学等众多学科的交叉学科。 在控制论中,「控制」的定义是:为了「改善」某个或某些受控对象的功能或发展,需要获得并使用信息,以这种信息为基础而选出的、于该对象上的作用,就叫作控制。由此可见,控制的基础是信息,一切信息传递都是为了控制,进而任何控制又都有赖于信息反馈来实现。信息反馈是控制论的一个极其重要的概念。通俗地说,信息反馈就是指由控制系统把信息输送出去,又把其作用结果返送回来,并对信息的再输出发生影响,起到制约的作用,以达到预定的目的。

这个思维模式又容易带来什么影响呢?

1、精确清晰的描述

系统嘛,任何一个部分描述的稍有差异,都可能造成很复杂很严重的后果。

如果你描述遗漏了什么,那么系统中就会存在一个未知的「冲激」,这个「冲激」一定会引起一些莫名其妙的「响应」,甚至可能毁掉整个系统。

如果你的描述添加了什么,那么系统中就会存在一个不存在的「信号」,针对这个信号的一切准备不仅一定是无用功,还可能引入其他很多故障(或者因为依赖了这个不存在的信号而无法完成功能)。

如果你的描述歪曲了什么,那么针对它设计的后续机制一定会做出错误的判断、继而引起复杂的连锁反应……

因此,程序员无法容忍模棱两可的含糊措辞(其实一切工程师都有类似的怪癖),也特别善于捕捉可能隐藏着重大问题的异常描述——毕竟每一句客户说的吞吞吐吐的话后面,都可能藏着一大窝子惊喜。

2、根源

初入行的新人,在兴高采烈的排除了旧系统的一个bug后,几乎总是会遇到老员工的兜头一盆冷水:「你确定找到根源了吗?」

为什么一定要找到根源呢?

因为软件是一个系统。

一切bug,除了偶然的键入错误,一定是程序员思想认识上的错误造成的。这些错误在系统中传递,还会引发其他位置的异常;其他位置的异常继续传递,继续造成更多更诡异的异常……

如果你只是抓住了其中一个异常解决掉,那么根本上的错误就被遮掩了,就更难抓到了。

同时,你的解决方案显然也是基于错误的理解而设计的;它本身就很可能引起其它异常。

你在不相干的地方修的越多,这个系统的健壮性就被破坏的越彻底。

除非你能证明这个修改仅仅是使得某个模块更健壮了、而且并不会隐藏上一级传来的异常、而且没有其他意想不到的side effect,否则宁可留着错误,直到你找到真正的根源。

这种思路,配合还原论,使得程序员在谈论各种问题时,总是自觉不自觉的寻找「真正的根源」,而不是满足于头痛医头、脚痛医脚。

不过,和普通人谈论时,他会觉得你故作神秘。很简单的事你干嘛非要讲那么复杂?

3、隔离

基于追踪根源、控制错误传递的思想,程序员会积极主动的隔离问题。

只有隔离了问题,才可以尽量在接近根源处解决问题。解决根源,才可以避免错误四处扩散到处破坏,把问题搞得越来越严重越来越不可解决。

因此,当讨论系统A时,他们希望能把系统B彻底丢到一边;而为了能够把系统B丢到一边,他们会把每个系统「封装」进一个黑盒子里,只关注它的输入输出。

——我们不要管系统B出错怎么办,先把系统A搞好、制止错误的扩散;那些无法阻止的「真正的异常」可以罗列出来,将来在上层设计机制处理掉。

——好了,现在不要假设系统A坏了怎么办,我们把系统B搞好。自己做好自己的事,不要老拉扯别人!

尽量完成错误隔离,系统整体才能够有序健康的实现我们的期望——就是真出错了,也可以直接找到责任人,不至于来来回回踢皮球。

但这种「一个一个问题分别讨论」的态度,很容易被普通人看成书呆子——哎呀它们明明是相互关联的,你怎么能一次只说一个?

4、混沌

只要开发维护过一些不太简单的系统,程序员就会知道,「混沌」才是常态。

为了告诫新程序员们,避免他们把软件工程想的太甜,业界还有一本极为著名的程序员必读书叫做【人月神话】。

嗯,这本书并不是讲嫦娥奔月的。

它说的是,不要以为一个项目的进度可以用简单的几个人、多少月就能做完衡量,这只是个神话。

增加人手,未必能加快项目进度;一个人两个月能做完的,两个人一个月未必能做完。没有任何工具、方法可以彻底解决这个难题。

因此,对于复杂系统,一个经验丰富的程序员一定不敢对你拍胸口;对于涉及大量人群的复杂事件,一个合格的程序员一定会想到「看似简单的XX与XX的交互也可能衍生出很多问题」。

如果一个程序员看不出其中的复杂性,那么他一定没有做过有一定规模的系统。

需求阶段的一个问题,流传到总体设计阶段就需要十倍的时间金钱精力投入才能解决;总体设计阶段的一个问题,流传到详细设计阶段,也需要十倍的时间金钱精力;详细设计阶段的问题,到了编码阶段,同样会被放大一个数量级……

最终,需求阶段的问题没有解决,推啊推推到编码阶段,将来你就得准备千倍投入……

因此,要应付混沌问题,你必须尽量在初始阶段就把事情做对——不需要多,但必须对。对了,将来才可能扩充;否则,初始阶段遗留的某些问题,修复它可能比重新写一遍的投入还大。

但和普通人谈论时,他同样会觉得你故作神秘。很简单的事你干嘛非要讲那么复杂?

5、控制论

面对复杂的系统,普通人会觉得一团乱麻:哎呀这怎么可能理得清?你胡说我胡说大家都胡说而已……

但是,很多时候,控制论可以快刀斩乱麻:再复杂,归根结底也不过是一个「冲激-响应」的问题。一个一个的把冲激输入找出来,分别讨论它的响应、分析它的因果,这不就理清楚了吗?

「控制论」已经被很多学者用到了历史研究等方面,它的确是一个极为犀利的武器。

混沌等于状态迁移特别特别多、初始条件又极端敏感;但混沌并不等于不可分析。

而程序员的工作,恰恰就是找出任意复杂系统的关键点、通过几条规则破解它。这个破解的捷径,就是利用控制论方法理清系统每个局部的相互关系。

但这种思路则很容易被不明就里者当作「头脑简单」,因为程序员总是只看得到一个原因;尤其搭配上「隔离」,就更显得「简陋」了。

问题是,「简陋」的「隔离讨论」并不是永远隔离;分别讨论完了(还原论)、再集成回去(系统论)不就把一切都说清楚了吗?一切不都在那几个公式/逻辑里面吗?综合一下不会吗?

嗯,说不定还真不会……

当然了,很少有人能把这些真正修炼到位。因为修炼不够,把这些东西用成笑话的比比皆是(我就经常闹各种笑话)。

对绝大多数人来说,只是因为这个环境的影响,从而在思想上打下了这方面的烙印而已——烙印究竟有多深刻,这当然是因人而异的。

但总的来说,程序员多半都受过这些思维方式的影响。这是这个职业本身的特点所决定的。