小哥公司

编程就是把复杂的问题简单化,让每一个动作都简单到1+1=2,然后计算机就会去做。这就是我对编程的理解。学姐听到这里,若有所悟,也就没有再聊这个话题了。

我们来分析一下电脑的特点。准确的说,目前我们社会的计算技术还很原始。说它是计算机没错,它只会计算。说它是电脑也太抬举了,它不可能有思维能力。

在冯诺依曼架构中,计算设备是这样一种具有一定计算能力的设备,具有与外界交互和高速重复动作的能力,这可能和你在课本上学到的不一样,但我是这样理解的。

所以,从一开始我就没有把计算机当成一个伙伴,一个可以代替我帮我出主意或者思考的伙伴,只是把它当成一个工具。这个工具有什么用?我认为最重要的是它有两个功能:

1,无限重复,一个动作序列,一旦编好程序,计算机可以重复这个序列无数次而不觉得累。这个特别适合那些枯燥重复的工作。比如在我们学校,每天上课都要敲钟,要敲钟。如果有人去做,这个人会很无聊,做久了可能会出错。但是电脑做的话,就没有思想,不会觉得累,会做的很好。电脑特别适合重复性的工作。

2.服务质量的稳定性。电脑适合重复性工作,还有一点就是每次结果都一样。这反映了工业化时代最重要的一个思想:大规模生产思维。如你所见,当今社会,不可复制的艺术是好的,但大众需要的是量产的产品,因为质量和产量稳定,能满足大众的需求。劳斯莱斯虽然漂亮,但大多数人开的都是大众、丰田等低端车。事实就是如此。还是敲钟的例子。如果是人,他可能会生病,请假,或者干脆忘了,但电脑不会。只要有电正常工作,打铃就不会出错。

就这样,我渐渐明白了,电脑其实就是一台可以不断重复输出服务的质量不变的机器。

好的,我们能不能先理解为计算机编程其实是人类的工作?当我们满足一个服务需求时,我们会做一次,做好,并得到一个满意的结果。然后我们认为这个动作可以重复。下次我们遇到类似的问题就这么做吧。所以,我们安排电脑来做。对不对?

这是不是意味着程序其实是在讲一个事情怎么做,做的过程,这个过程的意义其实是人定义的,然后编程教给计算机去做?

我以前有一种感觉,计算机编程有两层意思。一个是程序本身的意义,也就是怎么做事。另一个是程序下隐含的逻辑意义,也就是做事的意义。程序只有字面意思,而逻辑是程序段落组合在一起表达的一层意思。现在想想,其实就是这个道理。

好吧,既然我们知道编程就是把做一件事的步骤拆分出来,教会计算机去做,但是拆分到什么粒度呢?这一点非常重要。如果拆分的粒度太细,会浪费程序员的时间和精力,这些都是成本。而且分解太粗,电脑还是看不懂,做错了就是bug。

这说明编程中有一个很重要的概念,就是粒度,也就是我们对问题描述的精细程度。

第一台电脑最笨。学过计算机组成原理的同学大概都知道,只要有累加器,其实就可以算作计算机,只能做加法运算。因为从数学上我们可以知道,任何计算最终都可以演化为加法计算。其实现在的CPU,在底层核心,还是这个加法逻辑。

当然这个没什么问题,但是有个小问题,就是颗粒太细了。如果一切都要由程序员分解成非常详细的加法计算,这个工作几乎不是人的事。没有解决办法吗?

呵呵,就像我们之前说的,电脑有什么特点?无限重复,我们会发现一个东西,比如7*24,是乘法运算,但我们最终会把它拆解成加法运算。但是,并不意味着我们每次都要拆解它。乘法计算也是一项工作和规律。所以我们拆解一次之后,当然可以把拆解过程本身编译成程序,下次遇到类似问题的时候让计算机再运行这个程序。呵呵,你觉得Intel的CPU里的乘法指令是怎么实现的?你认为AMD的CPU内部的微码系统是如何实现的?

正是这种思维解决了所有的问题。当我们满足需求的时候,首先要拆分,然后不断搜索之前是否拆分过。当我们遇到适用的程序段时,可以直接使用,不用每次都拆分得那么细,减少了工作量。当然,遇到新问题,还是要自己拆解。但是反汇编之后,最好把反汇编本身写成程序,下次再用。

当人们玩各种语言时,他们通常会提供一个基础库。这个基础库其实就是之前反汇编的结果。软件公司认为它具有代表性,可以满足大部分应用,所以把它编译成基本库,程序员以后可以直接使用,不用自己重复。你这样认为吗?

现在你知道如何看待c的基本库了吧,比如stdio.h,stdlib.h?C++中iostream是什么意思,你知道吗?MFC知道吗?Java的运行时库也是什么意思?

但是,这个世界永远有大量的需求,计算机的能力也在不断提高。以前不适合电脑的东西,现在逐渐适合了。所以每个人总会遇到一些新的问题,需要自己去拆解。基本库不提供它们。这才是程序员这个职业存在的真正意义。帮助用户拆解新需求,解决新问题。当然,库本身也在改进,不断把已经被证明拆解成功的问题补丁到库中,避免以后程序员重复劳动。就这么简单。

呵呵,啰嗦了这么多,可能很多同学都糊涂了。小哥先生你想说什么?

我想说的其实很简单。编程就是反汇编的问题,但是要注意反汇编的技巧和方法。不要做别人以前做过的,尽量用。如果没有,就做一次,尽量留着下次用。就这么简单。

那么,这和本文的题目“修炼编程内功”有什么关系呢?

当然有关系。编程的内功是什么?我的理解是对世界进行抽象理解和描述的能力。一个作业可以快速提取下次可以重复的套路,可以用一定的规则来描述,也就是计算机语言规范。有了这两个能力,就可以保证遇到任何问题都能写出程序。

所以大家在学校学了很多数学,语言,算法,数据结构,甚至编译原理,操作系统。其实这些都是工具,不是写程序的目的。

写程序是指当你遇到一个需求时,你能快速抽象它,理解它的共性,并用清晰的语言描述它。以上科目要么有助于提高你的抽象能力,要么有助于提高你的描述能力。你认为这是事实吗?

所以我带徒弟的时候,有时候喜欢说一句话。其实作为一个程序员,学一点中文就好了,因为其实最能培养描述能力的还是中文。英语不算。虽然英语也是一种语言,但中国的教育一般都是可以理解的,学生的英语描述能力很少从一个英语作家的角度去培养。只有我们语文课,不仅教语言,还通过无数的句子和作文,教人描述问题的组织能力。这种能力在编写程序时非常有用。

这个时候,话题就出来了。中国的语言,先有甲骨文,再有文言文,再有白话文,我们发现没有,总体是越来越简单,这是发展趋势。为什么?因为人们认为汉语是人们能看懂的东西,太深奥的东西不适合普及,没有生命力。相反,越简单的东西,普及的越快。

所以请注意,写程序时反汇编是为了简化问题,不是说描述问题晦涩难懂,这叫技巧。真正的程序员是简化问题的大师。

当然,从这个题目,我们能得出结论吗?其实编程本身的方法,编程本身的内部工作,都是没有语言特色的,比如C,C++,Java,PHP,Python。。。他们都用同样的方式做事吗?

所以我在这里提出,练习编程的内功是学习抽象能力和描述能力,与语言无关。换句话说,从任何语言开始,你都可以把内功练到极致,关键看你是否用心。

所以在我学习期间,我的建议,不要好高骛远,不要评价语言的好坏和平台的好坏,没有太大意义,你也不确定自己这辈子最终能发展到哪个平台和语言。拿起手边的书和老师教的课程,埋头学习,扎实学习。出来后,换语言比吃菜还难,呵呵。这是对J.J .问题的正式回答。

我们再来谈谈小果的问题。他列举了一个很偏颇的题目,就是有a和b两个变量,没有if和?:,switch或其他判断语句,求两个数中较大的一个。

我觉得这个问题不好,所以提出异议。主要原因是基于上面的讨论,我认为评价一个程序员的标准应该是他简化和描述问题的能力,而不是他把问题复杂化的能力。

这在学院派是很多的。不要在这里生气。我知道大家现在大学基本都是计算机专业,是学术派,但是肖老师的观点和大家不一样。

在学校里,老师的任务就是尽可能多的教大家东西,因为他不知道你以后会做什么,什么知识是没用的。所以学校老师会尽力培养大家对复杂问题的描述能力,这就导致了学校的考试就是尽可能的把问题复杂化,考查更多的项目。学校里的氛围也认为解决复杂问题是高手,哪怕问题本身并不复杂。每个人都让评估自己的能力变得复杂。

但实际工作中并非如此。在实际工作中,大家最看重的是用最简单的方式解决问题的能力,因为这样成本最低,无形中大家赚的钱最多。所以问题的抽象拆解和清晰描述非常重要。

很多同学刚上班,会很不适应。其实就是这种观念的转变。在大学里,复杂是美,而在商业公司里,简单是美。这应该是很大的思想转变,甚至是世界观的转变,很难。一般来说,转得快的同学在公司进步更快,但我也见过干了几十年都没转过来的程序员。一般住公司都有点累。

建议大家思考一下我今天说的话,看问题,抓住本质。只要你能及时了解商业公司的发展思路,懂得简约的元素,我不敢说你一定能找到工作,但只要你找到了,基本上就能很快融入公司。