This commit is contained in:
louzefeng
2024-07-11 05:50:32 +00:00
parent bf99793fd0
commit d3828a7aee
6071 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,155 @@
<audio id="audio" title="不定期加餐1 | 远程办公,需要你我具备什么样的素质?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/66/2b/667b7c82116a5961a1f9a7749637652b.mp3"></audio>
你好,我是宫文学。到这里,咱们课程的第一模块“预备知识篇”就已经更新完了。通过这么多讲的学习,这些编译技术的核心基础知识,你掌握得怎么样了呢?是不是感觉自己已经构建了一个编译原理的知识框架了?
不过我也知道,要理解编译技术的这些核心概念和算法,可能不是一件很容易的事儿,在跟随我一起探索编译之旅的过程中,估计也耗费了你不少的脑细胞,那咱们是时候来轻松一下了。
今天,我就想借着这个加餐的环节,跟你聊一聊一个很有意思的话题:**远程办公**。
之所以选择这个话题,主要有两方面的原因。
首先,由于疫情的影响,春节之后,很多公司都采取了远程办公的方式。所以,如何在远程办公的情况下做好工作,对于员工和公司来说,都是一个挑战。
第二个原因,是我个人一直对于远程办公这种工作模式很感兴趣,这些年来也一直在做这方面的思考,关注这方面的实践,所以有了一些心得体会,想跟你分享一下。
不过,要想把远程办公这个话题聊清楚,确实不容易,分歧也比较大。有一些朋友会比较悲观,觉得远程办公根本不切实际;而另一些朋友则会很乐观,觉得远程办公马上就会普及。
今天,我就来分享一下我看待远程办公的一些视角。我会从公司和员工这两个角度,来分析远程办公带来的机遇和挑战,希望能给你带来一些启发,让你以更积极和务实的姿态,迎接远程办公的浪潮,甚至在这种工作模式转换的趋势下,抓住更多的发展机遇。
首先,我来聊一聊远程办公的那些吸引人的地方。
## 远程办公的好处
我对远程办公的了解最早是透过开源圈的朋友了解了一些故事后来自己也接触了一些酷酷的公司。很多做开源软件产品和技术服务的公司都是远程办公的他们的员工可能来自世界各地。我曾经接触过一个芬兰公司的CEO他们主要做嵌入式Linux的技术服务。一百多人的公司平常办公室是没什么人的。据说他们公司有的员工可以一边上班一边去全世界旅游。
我当时认为,一百多人的公司,全部都能远程办公,并且管理良好,就已经很不错了。但后来看了[一篇文章](http://www.geekpark.net/news/255260)讲到WordPress的母公司Automattic有上千名员工分布在全球75个国家全部都是远程办公。这就有点令人吃惊了我才意识到在互联网时代原来远程办公可以适用于任何规模的企业。
这次疫情中IT领域的很多公司都大量地采用了远程办公模式包括谷歌、Facebook、微软等大型企业。
现在新闻上说,疫情之后,世界再也回不到过去了。其实我觉得,在很多领域,我倒是宁愿它回不去了。比如,远程教育;再比如,远程工作。
因为远程,意味着你获得了一个难得的自由:**位置自由**。
现代社会,我们苦“位置”久已!因为很多资源都是跟位置绑定在一起的,比如说,教育资源与学区房。
我在北京的很多朋友,他们在孩子上学期间,一直都是租房子住的,因为要住得离孩子学校近,而自己的房子会租出去。这种状态要持续到孩子上大学为止。
而对于若干都市白领来说,在大城市上班,就意味着要把整个肉体在办公室和家之间移动,所以每天可能要在路上花两三个小时,很多时候还会在路上堵个半天。
如果我们真的获得了位置自由,那么整个生活的幸福指数会提高一大截吧!
对于远程教育来说,我比较希望见到的现象,是在偏远的乡村,一样能够通过线上教育获得最优质的知识资源。至于线下的老师,更多的是关注孩子的健康成长,多带着孩子亲近大自然,扮演“育”的角色,而不是“教”的角色。
工作也是一样。现在越来越多的工作,都可以在网上进行了。互联网电商的发展,虽然让一些线下店铺的营业状况受到了影响,但只要能通网络,很多人在网上就可以卖东西了呀。另外,随着外卖的兴起,很多餐饮企业也不再需要临街的店面了。
所以,通过远程办公,我们可能就不需要北漂、深漂等各种漂了,可以选择离自己的亲人更近一些,或者可以反过来,四海为家。并且,你还可能获得更多、更好的工作机会,你可以从全世界的公司里选择你喜欢的那份工作,并且也不需要离开你喜欢居住的地方。
并且,伴随着位置自由,往往也会给我们带来**时间自由**。因为远程后不再需要按时上班打卡了(很多在全球都招揽人才的公司,大家的作息时间都不一样,当然不可能统一打卡),所以管理体系会更加面向绩效,而不会管你到底是在什么时间来完成这些工作的(通常也没法管理)。这就意味着,你可以在家人需要你的时候,出现在他们身边(比如接孩子),然后选择自己合适的时间段来工作。
上面说的是远程办公对员工的好处。从企业的角度来看,远程办公其实也会带来一些潜在的好处。
**首先,有些员工可能会在工作上做更多的投入**(这跟某些员工会偷懒恰恰相反,所以可能出现两极分化)。这些人很享受自己的工作,每天上下班反倒降低了他可能做出的贡献。如果公司有一套良好的管理体系,那就可能会因此筛选出更适合自己的员工,而避开那些混日子、划水的员工,整个团队的素质反倒会得到提高。
我曾经跟MySQL的前CEO Mårten Mickos聊天。我问他**管理远程办公的员工,需要注意些什么?**
他思考了一下,说要建议员工跟家人一起住,至少要养条狗什么的。因为家人能帮助管理这些极客们的作息。不然由着这些极客们的性子,他们会昏天黑地、毫无规律地作息,不利于健康。就算养条狗,你也会因为要照料它们,而让自己的生活节奏健康一点。
他的回答其实出乎我的意料,我原本以为他会说什么公司的管理措施之类的。你体会一下,如果你是公司老板,你是不是会因为拥有这样热爱工作的员工而感到欣慰呢?
**第二,因为没有了地域限制,公司也就可以充分任用全球各地的人才。**这个方面在很多做开源软件的公司那里,得到了很好的体现。如果你喜欢某个开源产品,在社区里贡献自己的力量,那你很可能就会被邀请加入到该公司。
在互联网时代企业的组织方式也正在重构。滴滴打车、美团外卖这些采用新雇佣方式的公司不但可以更好地利用各地的人力资源TA们也提供了一些自由工作的机会。
**第三,没有了地域的限制,公司也可能更容易拓展自己的市场。**这个好处也是显而易见的,就不用我多说了。
## 远程办公的挑战
上面是我对远程的一些美好的憧憬。还是回到现实吧,因为更改现有的教育体制,可能是很难的。而让企业老板们改变公司的管理方式,难度也不低。
老板们都是理性的。真金白银投入做企业,是要见到效益的。可是,**如何能保证采用远程办公模式,不会让企业变成一团散沙,纪律涣散、效率低下呢?**
你可以问问,在春节后不得已实行远程办公的企业,对经营有没有产生影响。
说实话,在没做好充分的准备之前,仓促地采用远程办公,肯定会产生各种不适。
**因为远程办公,对于管理体系,有着更高的要求。**很多工作是难以直接度量绩效的,比如说研发工作就比销售工作更难衡量绩效。
而没有良好的管理体系仅凭员工的自觉是不可能产生良好的效果的。其实硅谷有一些IT公司很早就实行过远程办公但后来又取消了原因就是绩效不理想混日子的员工太多。
反过来,站在员工的角度,你真能做好自己的工作管理吗?在办公室工作的时候,迫于同事们的目光,你总得做点事情吧。可是,如果脱离了直接的监督,有多少人能够真正管好自己呢?
你说你的自我管理能力强那么请问有多少人能控制住自己每天刷手机的时间呢据说超过50%的成年人,都有手机上瘾症。在办公室的时候,尚且见缝插针地刷手机。如果在家办公,又会怎样呢?
有过远程工作经历的人都会经历这么一个时期。即使是你很有责任心、很有事业心但也要每天花费很多的精力来管理自己的行为。我认识的一个朋友她在IT行业主要做售前支持工作。之前跟她闲聊的时候她说自己花了3年的时间跟自己搏斗才养成了良好的居家工作习惯。而管理自己这件事情也是消耗注意力的。注意力本身又是个稀缺资源。所以在初期你会觉得对比在办公室里居家办公会更累在公司你不需要花精力来控制自己的行为因为环境和同事帮忙做了这件事情实际上节省了你的注意力。
我也听说,有的工程师会在网上直播自己编码的过程。这样做的一个原因,就是为了帮助管理自己的行为,因为这时候你必须更加集中注意力在自己的工作上。
**还有一个是办公环境的因素。**我们中国人的居住状态比较拥挤,在自己家里开辟出一个安静的、不被打搅的书房并不容易,这可能还跟中国的文化有关。而西方的文化,可能会更尊重个人的空间。
再说了,我们跟外国人的居住条件也确实不同。西方发达国家很早就开始了郊区化发展,大部分人会住在郊区和小城镇,自然环境比较好。而我们中国呢,大部分住在小区的楼房里。
不过,如果真的远程工作了,你也可以不住在大城市呀。网上有些视频经常会吸引我,某夫妇在乡村翻新出一栋漂亮的别墅,还拥有美丽的花园,等等。其实我目前就住在一个自然环境良好的山上,只不过从这个村子去办公室也很方便就是了。
**远程办公还会产生心理上的挑战:白天晚上都在家里,会容易心理疲劳。**而换个环境,反倒会让人兴奋起来。我就有个感觉,在家里工作久了,效率就会降低。而这时候再回公司工作的话,反倒更容易集中注意力。
而且,**远程办公肯定也会降低沟通的效率。**一些互联网公司,在设计办公室的时候,会故意设计一些空间,方便大家偶遇,闲聊几句。而做研发工作的同学都知道,这种看似随意的交流,有时候能激发出很多创新的思维。而如果总是自己苦思冥想,往往很快就会走入死胡同。这种线下偶遇式的沟通,往往见到了就会聊个几句。但在远程办公时,如果大家互相见不到面,还真就不聊了。
## 面对远程办公,我们要做好什么准备?
所以,我们需要实行一些积极的操作,来更好地应对远程办公给我们带来的挑战,这样也能更好地抓住远程办公给我们带来的机遇。
### 从公司的角度出发
那首先,我们来看看,对于企业来说,都需要做好什么准备。
**第一,我觉得企业管理者要建立一个意识:远程办公是企业必须要面对的管理考验。**
其实只要企业做大了,几乎都要面对远程管理的问题。比如你有了分公司,或者在各个城市设门店,甚至把生意做到国外。那么,突破地域的限制拓展业务,本来就是对企业能力的考验,是企业发展中必须踏过的门槛。
所以说,企业也一样需要获得位置自由。这些分公司、派出机构工作的人员,对于总部来说,本来就是远程工作的。有了这个意识,管理者就会开始放弃旧的思维,拥抱远程办公。
**第二,从看住人,转换到管绩效。**
很多比较传统的企业,他们的绩效标准都比较模糊,所以在远程办公的形势下,我们需要把绩效标准的清晰化、准确化放到第一位。像滴滴、外卖这些新职业,之所以能够迅速扩展规模,充分利用社会化人力资源,就是因为他们的工作绩效的标准是清晰而准确的。
**第三,建立拥抱远程办公的文化,给员工授权和赋能。**
像软件研发类的工作,它是知识密集型的,对员工的绩效评估比较难,人员更换的成本也相对较高。那么对于这类工作,我们可以多向那些开源软件公司学习,建立一个拥抱远程办公的公司文化,去吸引那些对工作充满兴趣和热爱的人参与进来。这些人,也会更加珍视公司给予的授权和自由。
**第四充分利用IT技术。**
管理一定要落实在工具上。我接触的那家芬兰公司就花了很多年的时间积累了一套成熟的内部管理系统。比如说作为软件公司你肯定要对项目进度、代码量、Bug数等基础指标有所管理才行吧
信息技术成本的降低也大大降低了远程管理的开销。这次疫情促进了视频会议在全世界的普及。对于中国的中小企业来说甚至可以0成本享受高品质的远程会议服务这真是一个了不起的福利
### 从员工的角度出发
OK说完了公司那我们再来看看从员工的角度出发我们都要具备什么素质才能更好地迎接远程办公模式。
**第一,员工也要建立一个意识:无论是否远程办公,都要向绩效负责,管理好自己的工作。**
即使你仍然在传统的办公模式下工作,如果你能像一个远程工作者那样对绩效负责,管理好自己的注意力,我想你很快就会获得领导的注意,从而赋予你更大的工作自由。你有没有听说过,张小龙经常睡懒觉迟到,而马化腾从来不管他?因为马化腾需要的是一个能做出微信来的张小龙,而不是一个每天按时打卡的张小龙。
**第二,正视远程办公对自我管理的高要求,养成良好的工作习惯。**
在办公室工作,会有环境来约束你。而当真的给了你位置自由以后,你其实要珍视这种自由,给自己定一些规矩,甚至给自己找一些监督(就像前面说的在网上直播),从而养成良好的工作习惯。
**第三,建立激进的协作习惯。**
由于远程工作对于协作的挑战,你必须建立激进的协作习惯,而不是仅仅停留在我们目前使用即时通讯工具和视频会议工具的习惯上。比如,你可以全时间视频在线、主动找人线上闲聊一小会儿、主动创造一些与人沟通的机会,等等。
**第四,可能是最重要的:为兴趣而工作,为自己而工作。**
人在没有很多督促的情况下,真正能驱动自己前行的动力,就是兴趣了。这个时候,你会把工作看作是促进自己成长的必要因素,从工作中成长,从成长中获得快乐。这个时候,你已经不是在为公司工作,而是为自己而工作。这样的人,才算获得了真正的自由。
## 小结
今天,我们讨论了远程办公对公司和员工的好处、挑战,以及我们需要做好的准备。我讲了两个主要的观点。第一个观点是对企业的:远程办公管理能力是企业未来必须具备的能力。第二个观点是对个人的:只有能够管理好自己的人,才能抓住远程办公带来的机遇。
那总体来说呢,信息技术的进步是不可阻挡的,它对于工作和生活方式的重塑,也绝不会停止。所以,远程办公一定会越来越成为现实,不管是对于企业还是员工,我们都要积极拥抱这样的未来。
## 讨论一下
**你有想过,有一天会通过远程办公的方式上班吗?远程办公有哪些地方会吸引你?你有通过远程办公的方式上班的朋友吗?你觉得,为什么远程办公现在还没有真正普及开呢?**你可以在留言区里,跟大家交流交流你的看法。
感谢你的阅读,欢迎你把今天的内容分享给更多的朋友。

View File

@@ -0,0 +1,156 @@
<audio id="audio" title="不定期加餐2 | 学习技术的过程,其实是训练心理素质的过程" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/36/f3/36188878f0byyd7f4e9e7af8fef568f3.mp3"></audio>
你好,我是宫文学。
最近,高考刚刚结束。每年一度的高考都牵动了很多人的心,学生和家长们都把高考看作是人生的一大关键关口。可是,等上了大学以后呢?很多同学也会感到不适应,因为缺少了一个像高考那样明确的学习目标,也没有老师和家长在旁边不停地鞭策和关注。到了工作以后,就更是如此了。
对于进入计算机领域的人而言呢,很多人迫于找一份好工作的压力,会刻苦学习一段时间,包括参加各种学习班。而一旦获得了一份工作,融入职场以后,很容易就进入舒适区。**反正当前的工作也能应付过去,为什么还要费力再去学呢?毕竟,工作已经够辛苦了。**
在这种情况下,人生的第二次转折点就出现了。
有的人能够管理好自己充分利用各种时间和机会不断地加深自己对技术的理解。虽然短时间看上去进步并不大但成年累月地积累下来效果就逐渐出现了TA们开始能够胜任一些关键岗位成了技术领头人。而另一些人则只能掌握那些比较容易掌握的技术时间一长就会显得平庸等年轻人赶上来的时候就更加没有竞争优势了。虽然这不是像高考一样能马上分出重点大学和普通大学的差别来但在进入职场5年、10年以后这两类人在发展上的差别并不比高考带来的差别小。
我说这些,不是在贩卖焦虑,而是想引出我们今天要讨论的话题:**从心理的角度看待学习技术的过程**。特别是自己管理自己学习的过程、跟自己相处的过程。
学习没有轻松的。尤其是学习像编译原理这样的基础技术,就会显得挑战更大。想要学好它,调整和保持一个良好的心态是非常重要的。而通常,我们在心理上会面对三大问题:
- 第一,我为什么要学习这么难的技术?学一些比较容易的、应用层面的技术不就行了吗?**这是学习的目的和动力问题**。
- 第二,以我的能力,能学会这么难的技术吗?**这是自信心和勇气的问题**。
- 第三,如何看待学习中经常遇到的挫折?总是找不到时间怎么办?等等。**这是学习过程中的心态调节和习惯养成问题**。
如果对这三方面的问题,你都获得了清晰的答案,那么你应该就能保持好持续学习、终生学习的心态,从而对自己的人生有更好的掌控力。
那接下来,我就给你解读一下,我对于这三类问题的理解。
首先,我们来说说**学习目的**问题。
## 为什么要学这么难的技术?
在做课程设计的时候,我和编辑同学都会尽量想着如何让这样的基础技术和你的日常工作关联起来,让你觉得它不是屠龙之术,而是能够在日常工作中发挥实际效用的。这确实是学习基础技术的收获之一。
不过,如果想长期坚持下去,我会建议你把心态调整成一种更高级的模式。用中国文化中的一句话来形容,就是“用出世的态度,做入世的事情”。如果一件事情你觉得应该去做,那就去做,不要太斤斤计较一些功利层面的东西。
那么对于学计算机而言什么是我们应该去做的呢那当然是要了解计算机领域的那些最基础的原理呀。如果搞了一辈子IT技术却不明白其中的道理那岂不是一辈子活得稀里糊涂的
我知道,大部分人不注重基础性知识的原因,可能是觉得它们不会马上发挥作用。可是,**那些最重要的知识、那些构成你知识结构的底蕴的东西,往往就是那些看上去不会马上有用的东西**。
我个人非常欣赏复旦大学做教育的一种态度,就是教给学生**无用之学**。哲学、艺术、写作、演讲、逻辑学、历史等知识在西方教育中被称作Liberal Arts我们有时候翻译成通识教育或者博雅教育。这些教育对于我们从事任何专业的工作都是有用的。
比如说,美学素养。一个设计良好的系统架构,一定是优美的。新东方的元老之一王强,在美国学习计算机的时候,会把写完的程序拉开一定的距离看。如果看上去不够美观,那一定是程序设计得不够好。
你乍一听上去,可能会感觉是无稽之谈,但有经验的程序员一定会认同这个看法。那些写得有问题的程序,往往本身就是又臭又长、非常难读;而高质量的程序,往往是模块划分清晰、简洁易读的。做不出好的系统设计的人,肯定美学素养也不够高。像爱因斯坦等大科学家,往往驱动他们做出某个研究成果的动力,就是想去发现一条更加简洁、更具优美感的公式,因为真理往往是简洁的、优美的。
我之前公司的一名股东,他以前是一位很厉害的软件工程师,后来被一个外企挖走,担任了多年的销售副总。挖他去外企的原因,就是因为当时该外企刚开始在中国推广中间件的概念,他听了介绍以后就说,那不就跟我写的某软件的原理是一样的吗?并且一下子就说出了这类软件的关键技术点。于是,该外企下定决心要把他挖过去,并且是去负责销售。去年,他突然又写了一套科幻小说,名称是《云球》。我这里不是为他打广告,我是想说,做一个优秀的软件工程师、担任销售副总和小说家,这三个职业从表面上看相差很大,但其实背后依赖的基础素质都是一样的,都是那些乍一看上去没用的基础知识、基础素质。
所以,从这个角度,我是同意素质教育的理念的。**一个缺乏美学素养、哲学素养和沟通能力等素质的软件工程师,潜力可能是有限的。**
说到基础素养,我补充一个例子。有一次,我和前面说到的这位朋友在一起聊天,结果一个软件公司的老总给我们吹嘘他们公司开发的某软件平台。在说到一些特性的时候,听得我俩目瞪口呆。后来我们告诉这位老总,他声称的东西违背了基本的物理学和信息学的规律。在违背科学的底层规律的方向上做事情,那就相当于去造永动机,根本是虚妄的。这是很多项目失败的根本原因。
而另一些人,却具备抓住事情本质的能力。众所周知,马云并不懂技术。但就是不懂技术的马云,在懂技术的马化腾、李彦宏都认为云计算不是趋势,只不过是新瓶装旧酒的时候,果断拍板做云计算技术。期间,来自内部的反对声一直很强,大家都不愿意在内部使用尚不成熟的云计算技术。然而时间证明,马云的眼光更准。并且,力主开发云计算技术的王坚博士,他自己的专业也不是计算机专业。那么,为什么一拨非科班人士会比科班的技术大佬们看问题还准呢?我想可能是他们的无用之学学得更好,基础素质更全面吧。
所以这就是我对于像编译原理、操作系统、算法等基础知识的态度。你就把它们看做是无用之学好了。我不仅鼓励你把这些基础知识学明白并且我也希望你可以尽量再往深里挖一挖。比如像图灵那样去思考一下计算的本质到底是什么编译原理用到的形式语言也可以被继续深挖从而跟整个西方科学体系底层的形式逻辑体系挂钩以此去深入地理解希尔伯特猜想和哥德尔定理了解面向对象、函数式编程这样的编程范式跟人类的认知和思维模式的关系跟Lamda计算、范畴论等数学工具的关系你还可以去了解复杂科学领域的成果并用这样的思维去看待大型复杂的信息系统。
如果你觉得编译原理这样的技术没啥用,那你一定会觉得我刚才说的那些更加没用。但我知道,一个优秀的软件工程师,其实一定是对我说的那些话题有所涉猎、有兴趣的。
总结起来,**一个人的基础素质,决定了他的思维方式、思维质量和眼光,那些看上去没用的基础知识、基础原理,其实是真正做大事、承担重任所需要的素质。**那,你到底要不要去学习呢?
好,如果你认可我的观点,那么我们接下来再探讨第二个话题,关于**学习的信心**问题。
## 我能学得会吗?
很多人都会有一个担心,说某些基础技术、基础原理太难,自己的基础又不够好,那么能学得会吗?如果学了半天又学不会,那不是白费力气吗?
从能力角度,我必须承认,**我们每个人都是有天赋的差异的**。你让一个普通人去跟姚明比赛打篮球,那不是难为人吗?
**学习这件事情也一样有天赋的问题**
我本人当年在高考的时候,是省里的前几名,但是等我到了北大,看到周围的同学通常也都是身手不凡;在记忆力方面,我也比不过很多同学,有的同学对普通的词汇书根本不感兴趣,会去背词典,甚至背专业领域的词典;在数学等需要逻辑思维的领域,我又比不过另一些同学,直到今天,对于一些涉及数学的问题,我都会去咨询这些同学的意见。
但从另一个角度讲,**一些基础知识、基础原理,一定要有很强的天赋才能学会吗?**
不是的。在人类知识的殿堂中,你要想增加一点新的理论、新的原理,那是非常难的。所以我们必须对那些大科学家们,那些计算机领域的先驱们顶礼膜拜。那些顶尖的工作,确实需要天赋,再加上努力和机缘。
不过,即使狭义相对论和广义相对论发明起来那么困难,但一般的理工科学生只要想学,都是可以弄明白的。这就证明了,发现知识和学习知识所需要的能力,是极大的不对称的。在高考季,经常会出现妈妈级、奶奶级的考生,从陪考到变成跟儿孙辈一起上大学的故事。人家奶奶都能考上大学,我们年轻大学生学不会本专业的一些基础原理,这个道理说得通吗?
同理你常常会听到的一个理由也是不成立的这个理由就是我不是科班出身。这个我就不认真去反驳了。你想想看吧费马的本职是律师而他“业余”是个大数学家数学家罗素却获得过诺贝尔文学奖比尔·盖茨进的是哈佛大学商学院我前面说的王坚博士是学心理的罗永浩的专业也肯定跟IT没关系刘慈欣是业余写小说的。
所以,那些所谓的困难,只是你给自己设的玻璃天花板。这不是个能力问题,而是个心理问题。**儒家提倡“智、仁、勇”三种最高的道德标准,勇气是其中之一,它也是我们应该训练的一种品质呀。**
好,如果你又一次认同了我的观点,那么我们再来讨论第三个问题,**如何克服学习过程中的困难**。
## 如何持之以恒?
在我看来,如果理顺了前两个问题,也就是为什么要学,以及信心和勇气的问题,那么你最大的心魔其实就破除了。
但毕竟,学习贵在持之以恒的坚持。在这个过程中,我们可能会遇到很多的困难。但对于这些困难,我们也要用正确的心法来对待。所以,接下来我就针对如何面对学习中的困难、如何保证学习时间、如何找到学习的乐趣等常见问题,谈谈我的看法。
### 困难是必须的
首先你得明白,有价值的东西,一定是要克服困难才能得到的,这是公平的。所以**不要指望学知识而不需要付出努力,再好的教程和老师,也只是起到辅助作用**。这里你得注意一个问题就是不要被某些书籍和课程收了智商税比如说“7天学会XXX”“学英语其实不用背单词”等等。这种标题就是违背学习的基本规律的。
所以,当你知道了苦难不可避免这个道理,那你剩下的就只有面对这些苦难。在学习中,你可能经常会被一个难点阻碍住,这很正常。你正确的心态应该是这样的:
- 没有我拿不下的山头,正面拿不下从侧面,侧面不行走背面。多换几个角度,多几次尝试,多看点参考资料,总会成功;
- 那么多人都能学会,我没有道理学不会,一定有更好的方法;
- 这个问题既然有难度,那价值一定也大,所以一定不要放弃。
有了这样的心态,其实再苦再难的事儿都好说了。
### 在旅途中发现乐趣
我一个朋友最近正在从新疆骑行到西藏全程3000公里中间需要穿越无人区。这是他第三次做这样的骑行之前已经骑过川藏线、青藏线。虽然过程很艰苦但沿途美丽的风景和跟自己相处的过程就是这个旅途给他的回报。
我自己也喜欢户外。我家人有时不理解我,问我为什么要开着一辆大房车去那么远,累不累呀。我说,这就是旅行的意义呀。如果直接飞机过去,那有什么意思。
我用这两个例子作类比,是想告诉你:**当我们学习那些有难度的知识的时候,其实肯定能发现出其中的乐趣来。**比如,在学编译原理的时候,你去动手实现几个小例子,哪怕还不到实用的程度,但是好玩呀!当你找到了其中的乐趣,那么别人看你是在艰苦地学习,但其实你是乐在其中呢。就好像,别人看着一个人是在顶风冒雪一个人骑行,但他也是乐在其中呢!
另外呢,在互联网时代,各种不需要动脑的娱乐方式层出不穷。普通的人会在这种廉价的快乐中流连忘返。**而如果你的目标是持续进步,那要培养自己另一种习惯,就是习惯于获得那些艰难的乐趣,这种乐趣是真正的充实的乐趣。**
### 跟自己相处
我前面举的朋友骑行的例子,他是自己一个人。我也喜欢自己开车出去,因为没有了其他人,也就避免了因为人际关系而导致的分神,你只需要关注大自然和你自己。你能感受到自己跟自己对话的过程,自己跟大自然对话的过程。
**学习在大多数情况下也是一个人前行的过程,学到的知识也只属于你一个人。**在这个时候,就只剩下了你要去攻克的知识,和你自己。你能感受到自己跟自己对话的过程,自己跟知识对话的过程。当遇到困难了,你能发现自己的苦闷和焦虑;当解决问题了,你能感受到自己的欣喜。
真正有价值的成绩,都是在这样的跟自己独处、跟自己对话的过程中做出来的。这是一种值得追求的素质。
### 跟志同道合者相伴
独行难,众行易。除了那些内心特别强大的、从来都不屑于与普通人同行的天才,我们大部分普通人还是愿意有一些同伴一起结伴而行的,这样会大大降低驱动自己所需的努力。
我在读研时曾报过GRE的培训班。我感觉报班的最大作用其实不是跟着老师学到多少知识而是培训班乌泱乌泱的一大堆的同学给我提供了一种气场让我每天不想别的赶紧学习就是了。
这样的群体还会有效改变自己的学习标准。在学GRE之前我觉得一天背几十个单词已经挺辛苦的了。但到了GRE班我很快就接受了每天背200个的新标准因为其他人也是采用这个标准的。关键是就算每天背200个我也没觉得有多困难。所以你看人的潜力有多大的弹性而一个好的群体就是能无形中给人提供这种心理上的能量。
而且那时的同学都会有这种体会,就是每天如果不背单词就不舒服,上瘾。那段时间,随便看到一个单词,脑子里就会出现几个近义词和反义词,这种感觉很奇妙。再次印证了我前面说到的那种奋斗中的乐趣。
在软件领域,有很多技术社区,这些社区也能起到对人的心理加持作用,你可以善加利用。
最后,如果有要好的朋友和导师,能够鞭策你,那也非常难得。有管理经验的人都知道,虽然我们希望每个员工都有自我驱动的能力,但**合适的外部驱动能降低员工驱动自己所需要消耗的努力**。毕竟,我们大部分人其实是愿意工作在“低功耗模式”,能节省能量就节省能量。
### 使用运营思维
在互联网时代各种App在功能设计和运营上充满了心理学的套路以便培养用户的习惯。游戏公司更是会雇佣心理学专家来设计各种套路。
那么,与其让别人套路你,不如自己套路自己,同样利用心理学的知识来培养自己的学习习惯,把自己的时间、自己的命运把握在自己手里,不是更好吗?
心理学的基础原理并不难你自己就能从各种App的使用套路里体会到一些。比如说对取得的成绩即时给予奖励。从心理学的角度、从各种App背后的运营者的角度来看我们每个人其实就是巴甫洛夫实验室里的动物而已。通过这样的自我训练你可以达到一些很好的效果
- 建立良好的学习流程,有明确的开始和结束时间;确认一下每天的学习目标和学习成果,或者可以建立学习过程的仪式感;给自己一个良好的环境。
- 没有学习的时间?那是不可能的。这是因为你没有给学习安排出专门的时间来。
- 以输出带动输入。很多同学有写技术博客的习惯,这个习惯非常好。因为你要写出东西来,所以会逼迫自己把思路理清楚。
- 激进一点的:直播自己的学习过程,给自己提供外部监督和激励机制。
## 小结
今天这一讲,我聊了聊对于学习比较难的、比较基础的知识的心法的理解。总结起来,主要有三点:
- 第一,那些基础知识的素养,决定了一个人的发展潜力,这是你要学习它们的原因;
- 第二,没有学不懂的知识,真正的障碍是心理上的自我设限;
- 第三,学习的过程,就是砥砺前行的过程,经常能自省和调整自己的状态,就能养成自己的学习能力。
那么,你对于学习,有没有什么好的心法?欢迎在留言区跟大家交流!
感谢阅读。如果你也觉得很有收获,非常欢迎你把今天的内容分享出去,跟你身边的朋友一起做会学习的人。
我们接下来就要进入到期中复习周了,到时候你就可以来看看,在前半段的课程中,你都学习得怎么样!

View File

@@ -0,0 +1,110 @@
<audio id="audio" title="不定期加餐3 | 这几年,打动我的两本好书" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/e8/1e/e822885f4a624b0297c776ba44b0cf1e.mp3"></audio>
你好,我是宫文学。
在互联网时代,读书好像变成了一件挺奢侈的事情。因为我们现在获取信息的主要渠道,已经变成了网络。不过,在互联网统治力如此强劲的今天,我偶尔仍能发现一些好书,让我可以放下电脑和手机,对着厚厚的一大本,从头看到尾,甚至还会看很多遍。可见这些书确实是真正打动了我,让我这个理科背景的人,能以新的视角来看待世界,理解这个世界背后的运行规律。
我觉得一本书籍能达到这个阅读境界就很值得推荐了,因为这相当于是在帮助我们树立世界观、沉淀方法论。所以今天的加餐环节,我想给你分享两本打动我的好书,或者说是以其为代表的两类好书,跟你聊聊我读这些书的感受和收获,希望也能给你一些启迪。
那第一本书呢,就是《失控》。
## 《失控》
失控这本书的作者是《连线》杂志的主编凯文 · 凯利于1994年出版。这本书被很多人推崇据说张小龙就曾说过谁能看懂《失控》这本书谁就可以到他那里工作。
这本书的神奇之处在于它虽然成书于上个世纪90年代初但准确预测了后来互联网时代的一系列的创新更厉害的是它揭示了互联网时代背后蕴藏的道理。就如这本书的副标题所说的它揭示了“全人类的最终命运和结局”。
我自己呢,是在读过这本书后,对其中的内容感觉极为惊讶。我甚至怀疑,凯文 · 凯利到底是何方神圣,为何他能够写出这样的惊世之作。
我就拿《失控》中第二章的内容,跟你一起分享一下,做一次管中窥豹。
第二章的标题是“蜂群思维”。蜜蜂是一种社会性昆虫它们总是一大群一起生活。在研究蜂群的时候你会发现一群蜜蜂相当于构成了一个单独的生命体这个生命体比单只的蜜蜂更加高级。举个例子单只蜜蜂只有6天的记忆力而一个蜂群却拥有三个月的记忆时间这是个体记忆与群体记忆的区别之处。另外这个生命体会比单只蜜蜂拥有更长的寿命且具有繁殖能力能分化出新的蜂群。
这样看起来,它似乎符合一个生命体的所有特征。而这种把很多个体连接起来,构成一个更高级的存在的现象,就叫做**涌现Emergence**。
另一个能很好地解释涌现的例子,就是人类的大脑。大脑中的神经元,实际上就是一个很简单的个体,它们只知道在接收到信号的时候,对其他神经元发送信号。而基于很多亿的神经元所涌现出来的大脑,却具备记忆、推理、情感等很高级的能力。试想,如果你是一个神经元,你其实是根本无法理解,以亿万个你构成的一个超级生命体,竟然会拥有情感、逻辑推理这种东西。因为在一个神经元的世界里,它只有接收信号和发送信号这两件事情。
你再往下思考,就会发现人类社会正是由亿万个你我构成的,那人类社会是不是一个超级生命体呢?这个生命体在思考什么,我们作为一个神经元级别的存在,如何能理解呢?或者说,思考仅仅是我们这个级别的个体所能理解的事情。而这个超级生命体所做的事情,可能已经根本不是人类的思考这种层面的事情了呢?早期人类的宗教,以及宗教中的神,也是高于单个的人类个体的。那么,它们是不是这个超级生命体在人类历史中早期的一种呈现方式呢?
我们再来假设一下,当前的互联网时代,连接网络的计算机、各种智能手机、智能设备越来越多,甚至已经开始接近大脑神经元的数量了。那么,它们会不会涌现出一个超级生命体?这个生命体是否会具备自己难以撼动的意志,而我们必须屈服于这种意志呢?
怎么样?这本书里的观点,是否也能同样给你带来启发,开一个大大的脑洞?是不是也引起了你去一读的兴趣呢?
这个级别的内容,在《失控》里还有很多。再举一个例子:活系统的特征是“摇摇晃晃的平衡”,而处于稳定的系统就进入了死寂。从这个角度看,如果我们的生活中问题不断,其实正是活系统的特征,因为我们要谋求持续的不均衡,这样我们才有机会去改变它,这总好过稳定的、死寂的生活。你看,这样的结论都已经带有了哲学的特征,让我们在面对生活中的挫折时,会采取更加积极的心态。
于是,还是回到我前头提到的那个疑惑:为什么凯文 · 凯利会有这么深刻的洞察力,远远超越我们这些普通人呢?
经过研究,我发现原来书中的很多观点,其实是对从上个世纪中叶以来,各学科的科研成果的总结,然后通过一个资深科技编辑的叙述普及给大众。看到这里,我才放心了:原来并不是出了一个多么逆天的天才,而是我自己对科技发展的新成果,以及其中蕴含的新思想缺少了解。这些思想或理论呢,包括了很多同学都知道的系统论、控制论和信息论三大论,以及后来的协同学、博弈论、突变论、混沌理论、分型理论、耗散结构和复杂性理论,等等。它们在过去的几十年间不断地发展,并正在形成一个宏大的、崭新的世界观和方法论体系。**现在的一个新兴学科——复杂科学,似乎就是这些元素的集大成者。**
我以前对复杂科学了解得不多,但我觉得其实也不能怪我。因为我们在中学、大学学的那些知识,大部分都是用来描述简单系统的。比如在大多数情况下,天体的运行就是一个简单系统,我们用相对论这样的理论就能准确地预测天体的行为。
而复杂系统,其构成部分之间的相互作用关系比较复杂,难以预测。我还是拿天体来说,三颗星体的相互作用,就变得难以预测了,这就是著名的三体现象,也是刘慈欣小说名称的来源。蝴蝶效应、混沌系统,等等,说的也是这个现象。
可以说,**复杂系统破除了对还原论的迷信**。也就是,即使你把一个系统分割成一个个的“零件”,并且完全理解了每个“零件”,你也可能无法理解整体系统。因为整体不等于部分的简单相加,比如说,就算你理解了一个社会的经济体中的每个企业和消费者的行为,你也无法准确掌控宏观经济。
**可是,了解这些,对你我有什么意义呢?**
我先讲一个小的用途。作为软件架构师,你其实应该知道,当一个软件系统复杂到一定程度的时候,你要把它看成一个动态演化的有机体。你对系统做的任何改动,都可能会引起一些你完全预料不到的结果。这就是为什么,你可以花一点儿钱甚至是免费就能搭建一套简单的电商系统,但是像淘宝这样的大型系统,则需要几千人来建设和维护它。
再举个例子。我们现在都非常熟悉的微服务架构它的理念是一个大型软件系统是从一个个分布式的、自治的单元中涌现出来的。流媒体巨头NetFlix他们也是微服务架构的首批推动者之一。在NetFlix软件工程师们会设计一些叫做Monkey的程序随机地杀死一些服务看看系统能否正常地自动修复。发现了吗像微服务这样的复杂系统它的冗余和自愈的能力已经像是一个生命体了即使出现了一些突发的故障比如某些服务的宕机它也不会一下子全部瘫痪。
除了软件领域,与人类社会密切相关的系统,包括天气系统、生态系统、经济系统、社会系统,甚至包括人体本身,它们也都是复杂系统,所以现在的很多学科都在采用复杂系统的思维做研究。比如,采用演化的思维做心理学的研究,就形成了进化心理学的分支(其实更恰当的翻译方法是演化心理学,因为演化是没有方向性的)。这个学科的基本逻辑,就是现在人类具有的某种心理特质(比如为什么恋爱中男人更主动,女人更矜持),都是在进化中形成的。因为凡是没有这种心理特质的人类,都已经在进化过程中被淘汰了。
再进一步,其实你根据上面的信息可以得出一个结论:原来文科生研究的对象都是复杂系统。**你一旦意识到这一点,你就可以通过复杂系统的研究成果,去研究原来属于文科生的研究范畴,比如说社会学、经济学、文学和哲学,从而拥有方法论上的优势。**
给你简单举个例子,经济学中的宏观经济学部分,就是针对复杂系统的。这也是为什么大家总是说经济学家都是事后诸葛亮的原因:复杂系统是很难被简单地驾驭的。
甚至,你也可以用复杂科学的视角来重新审视哲学,特别是一些古代的哲学思维。因为基本上这些古老的哲学思想都是复杂系统的描述,是让你能够更好地适应自然系统和人类社会这两个复杂系统的一些解。比如说,儒家的思想,是理顺人际间的互动关系,从而缔造一个稳定的社会系统;而道家的思想,则是描述了包含人类社会和自然界的一个更大的系统规律。
有意思的是,凯文 · 凯利在《失控》的最后一讲,总结了复杂系统的特征,有很多地方跟道家的思想非常契合。比如说,“世界是从无中创造出来的”“从无数神经元的连接中,涌现出了大脑;而分子层面的连接,则涌现出了细胞”。
可以说,从《失控》这本书开始,就引起了我对复杂科学的兴趣,这个主题下的其他书籍,比如《复杂》,也非常值得你一读。
好,接下来,我再给你分享另一类好书,是关于文化的。而且它跟复杂科学这个主题,也是存在联系的。
## 文化与地方志
我从大学起,就对“文化”这个主题非常感兴趣,跟东西方文化有关的东西我都乱看了一气。大学时我读过一本书,是房龙的《人类的故事》,非常喜欢,因为它不但描述了历史事实,还描述了推动历史发展背后的原因和规律。我当时想,如果历史都这么写,那么大家学历史的时候肯定不会觉得枯燥。
因为我的思维特点是非常理科生的,我很难记住那些相互之间没有逻辑关系的事实,我也很难接受强加过来的一套体系,除非我能弄清楚它背后的逻辑。而如果一本书,它能讲清楚事实背后的因果关系的脉络,就比较令人愉悦了。
而我前面所说的复杂系统的一些研究成果,就可以用来理解这些文化背后的逻辑规律。我挺喜欢的一个独立学者王东岳,他写了一本书叫做《物演通论》。王东岳很喜欢解读东西方文化背后的脉络,看他写的书就让人有一下子把厚厚的书读薄的感受,非常过瘾。
不过我想,如果我没有读过《失控》及其相关理论,我可能又会对王东岳此人惊为天人,对其著作惊为天书。但在有了前面的知识积累以后,我就不会那么惊讶了。因为王东岳先生的思考,也是建立在大半个世纪以来的科研成果的基础上的。物演的“演”字,就是演化思维的体现。当然,他能够进行提炼和再创造,构造一个完整的知识体系,也相当值得敬佩。
其实说了这么多,我的意思是,**文化可以用复杂科学的思维来解构**。这个方法,特别适合像我这样的、擅长逻辑思维的理科生们。每当你观察到一个文化现象,你都能解构出这背后的原因,岂不是很有意思呢?
作为一个北方人,我这几年大部分的时间都在厦门,对这里的闽南文化做了饶有兴趣的观察。去过厦门旅游的同学,应该都知道厦门的文艺气氛还挺浓厚的。那为什么厦门会有这种调调呢?还有,你在旅游的时候,应该会发现厦门的一种小吃,叫做沙茶面。那为什么沙茶面会在厦门文化中涌现出来呢?
这就需要结合闽南这个地方的地理、历史等各个要素及其互动关系来做分析。不过,我准备在课后的留言里,再分享我对这几个问题的看法。你有兴趣的话,也可以发表你的观点。
类似的文化方面的问题,还能提出很多来,比如:
- 为什么泉州会成为海上丝绸之路的起点?
- 为什么孔圣人出在山东,而历代出状元最多的省份,却都在南方?
- 中国有很多古镇,每个古镇在历史上肯定都是富甲一方的地方,那究竟是什么因素才促使它们兴盛起来的?
- 如果某个地方有一个地理标识产品,是某种柿子,你能推测出那里的地质特点吗?
- ……
去年的时候,我因为一个项目,翻阅了某县的县志,结果没想到我会对县志如此感兴趣,读得津津有味。我才发现,通过县志我能了解一个地方的地理、历史、经济、文化、重要人物等各种信息。通过这些信息,我基本上就能看到一个由很多要素相互作用构造出来的一个复杂系统,就能读懂当地各种文化的成因,这非常有意思。
中国的很多文化积淀很丰富。如果有机会能够一点一点地解读过去,那该多好。我估计我会一直保持阅读并解读地方志的兴趣。最近回老家,家人又给了我一本我们县在民国时代的县志。看着这些书籍,我有一种强烈的感觉:即使你是在这里生、这里长的,你也不一定真的了解本地的文化。
**我为什么会推荐你去读地方志和其他讲解文化现象的书,读懂自己的本地文化呢?**
第一层原因是呼应我在加餐2“[学习技术的过程,其实是训练心理素质的过程](https://time.geekbang.org/column/article/269322)”中,提倡你多学点“无用之学”的观点。哪怕只是让你的灵魂更有趣,不是也挺好的吗?
第二层原因,是我作为一个理科生的思维方式。把自己所处的社会系统理解清楚,能够透过现象看到后面的逻辑,不是很有意思吗?
第三层原因,如果你能够运用复杂科学的思维,来理解现在的社会系统,其实是有实际意义的。举个例子,如果你要撰写一个商业计划,或者想给一个企业写一套软件,这就需要你理解其当前的商业系统、理解一个企业组织具体是如何运行的。而你之前的这些阅读积累,就会成为你的底蕴,成为你的智慧源泉呀!
## 小结
今天这一讲,我推荐了两本书,或者说是两类书。一类书,是以《失控》为代表,讲述与复杂性相关的话题。另一类书,是以地方志为代表的文化载体。之所以给你推荐这两类书,是因为它们给我如何观察和理解这个世界开启了一扇窗户,并且给我这样一个严谨的理科生,提供了一条去打开文史哲的大门的独特的、有优势的途径,希望能对你有所启发。
## 思考一下
1. 你有没有阅读过《失控》?你对复杂科学有什么了解?复杂科学在你的领域里有什么应用?
1. 你对自己出生地的文化了解吗?你有没有曾经发现一个文化现象背后的逻辑脉络?你觉得多研究点文化现象对于自己的职业生涯有好处吗?
欢迎在留言区发表你的观点。如果今天的加餐让你有所启发,也欢迎把它分享给你的朋友。

View File

@@ -0,0 +1,125 @@
<audio id="audio" title="不定期加餐4 | 从身边的牛人身上,我学到的一些优秀品质" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/e2/73/e2edbd0d30aa4322013537674bfb9d73.mp3"></audio>
你好,我是宫文学。
今天的加餐环节,我想跟你分享一下让我很敬佩的那些牛人,以及从他们身上我所能学到的优秀品质。我希望你也能从这些人的故事上得到启发。这里为了叙述方便,我就不提具体的名字了。你只需要了解他的故事,从中有所感悟就好了。
我把这些牛人分为了两类,一类是搞技术的,一类是创业的。由于我自己也身兼两重身份,所以我很关注这两类人中能带给我启发的人。
首先来说说第一类人,搞技术的,也就是我们常说的极客们。
## 我所理解的极客
我曾经在技术圈子里参加过比较多的活动,特别是开源圈子的活动,因此也接触了不少技术大牛,国内国外的都有。
早在2000年的时候我就听过理查德·斯托曼Richard Stallman的讲座听他布道自由软件。Stallman是GNU这个组织的创始人他也发起了GPL开源协议。更重要的是他是GCC编译器的主要作者所以跟我们这门课也是很有渊源的。记得当时他给我们放一个幻灯片的时候用的是Linux上的一个软件界面没有微软的PowerPoint那么酷炫。但你能想到Stallman是绝对不会用PowerPoint的。
后来在参加和组织开源技术活动的过程中,我也接触了不少国内国外的技术团队,他们在很多方面刷新了我的认知、拓宽了我的视野,也让我更理解极客都是一些什么样的人。
在我看来,这些人应该就是合格的极客。那么,怎样才能被称为极客?是技术水平高吗?我想不是的。技术水平高,其实只是一个结果。真正让极客显得与众不同的,其实是他们对待技术的态度,乃至是对待人生的态度。这些特质,也能给所有做技术的人一些启发。
首先,是**热爱技术**。
跟普通人只是把技术作为一个谋生的手段不同,极客们是真心喜欢技术,热衷于钻研和探讨各种技术细节。他们在对待工作的时候,绝不会把某项工作做到能交差就行,他们想要做到完美。
我之前公司的一位股东,他在做程序员的时候,曾经接到领导的一项任务,给了他一块语音板子,让他研究一下能否做呼叫中心的功能。两个星期以后,再问他,技术上是否可行?他说,已经做完了。不仅做完了,他还考虑了各种扩展性。比如,给他的板子只有八个语音口,但他写的程序考虑了用不同的板子,有不同的口的情况。以至于后来很多年,基于他的程序做的呼叫中心系统,底层都不用做很大的改动。
我这位朋友,我在[加餐2](https://time.geekbang.org/column/article/269322)中也提到过。他因为对于底层软件的深刻理解力,被挖到中间件公司做老总。后来又在创业什么的,最近又写了一套科幻小说。不管什么时候,我总能从他身上吸取到一些东西。
另一个例子,是我一个在苹果工作的同学提到的。这位同学负责苹果的文件系统的开发,我下面还会给你讲他的故事。这里是他讲的另一件事情。一次,一位博士分配到他们组,一时没有合适的工作给他干,就先让他做一阵测试。结果这位老兄,彻底升级了测试系统,对于大量的工作都实现了自动化测试,给整个团队带来了巨大的价值。
这个故事也让我更新了看待测试工作的视角。我现在基本上不会去招聘那些因为对自己的技术能力没有信心,而选择去做测试工作的人。我认为测试工作需要极大的技术热情才能做好。
我想,不管是从事什么岗位,能够热爱自己所做的事情,都是非常值得庆幸的。反过来,如果不喜欢自己所做的事情,为什么要去凑合呢?
换句话说能够做自己喜欢的事情其实是有所取舍、有所牺牲的。林纳斯·托瓦兹Linus Torvalds就喜欢领着一拨人折腾Linux。如果他去做某个大公司的CTO甚至是创业合伙人也无不可。但他选择的是自己喜欢的生活方式。他没有太去想自己因此损失了多少发财的机会。
这就涉及到了第二点,就是极客们**洒脱的生活态度**。
极客们所展现出来的这个特质,从某种意义上来看是更具魅力的。很多极客,都是不愿意以“生活所迫”为借口,选择自己不喜欢的工作和生活方式。
我在[加餐1](https://time.geekbang.org/column/article/251164)分享远程办公话题的时候,就提到过一家芬兰公司。这家公司都是远程办公的,其中有的员工,是一边全球旅游,一边工作的。这些技术型的公司,正是以这种方式,吸引那些真正的极客加入。
还有一次我参加一个技术活动我的朋友C指着一个老外说这家伙在泰国买了一个小岛自己住还弄了个度假村什么的。说实话这样的归园田居的生活方式对像我们这样浸染在中华文化中的人来说是有很大的吸引力的。但我们有多少人敢于不从众去选择自己喜欢的生活方式呢
我还有的朋友是依托自己的技术创业的。创业这件事当然很不容易,但他们通常都会保持积极乐观的态度,并没有因为自己的项目没有及时被社会认可,就变得垂头丧气。
那第三点,就是极客们看待这个世界的方式:**用代码说话**。
极客这群人是不大讲政治的。他们一般只认真实的本事。Linus就有一句名言“Talk is cheap, show me the code.”,这也代表了极客们的精神。一个人的水平如何,看看他写的代码,或者至少看看他发表的文章,其实差不多就有数了,这个是伪装不了的。
早在智能手机流行前有一次聚会我一个搞Linux的朋友F就拿出了一台手机里面装着Linux、图形界面、App什么的看着都还行。这都是他鼓捣出来的。其实再加把劲比如支持用Java开发应用这就是一个Android系统了。而Android的创始人安迪·鲁宾Andy Rubin差不多也是这样一个极客。前一阵我跟一个公司的老总聊天。他问我为什么中国搞不出安卓来我给他解释了原因。其实不是我们没有这样的技术在极客们的眼里最早的那个安卓版本也没什么大不了的。只不过我们没有掌握技术生态而已。
极客们一般对系统底层的技术都比较熟悉。像安卓系统这种看似很高大上的东西,不会让他们心生畏惧。这些人在互相交流的时候,也会谈论一些底层技术。几句话下来,心里已经有数。
然后呢?他们之间会缔结惺惺相惜的友谊。两个极客之间的交往可以极其简单,他们甚至不需要见过面,只需要见过对方的代码,或者读过对方的文章,就会认可彼此。如果有事情,直接打招呼就行。
某互联网大厂是如何把自己的底层技术搞扎实的呢据我了解就是找到一个开源圈的大牛。这位大牛进去了以后又给技术社区的其他人打招呼说这里有什么技术难题需要解决过来吧。于是就聚集了一个小组的牛人搞出了非常好的成绩。这就是极客们的特殊的社交方式他们知道who is who并且志同道合的人愿意聚到一起。如果光靠HR部门和猎头公司来做要想达成这样的结果是很难的。
Github在某种意义上也是把极客们的这种倾向给充分地引导了出来。它从一个代码托管工具几乎已经变成了程序员的社交网站。
这里我是想说明一个观点,那就是技术人并没有怀才不遇这一说。**把真本事亮出来,所有的事情会变得简单很多。**
好了,这就是我总结的极客们给我的三点印象:热爱技术、生活洒脱、凭本事说话。这些特质,都是我很欣赏的,也常常作为参照来调整自己。
比如说,我觉得自己也挺热爱技术的,但是在前些年,我觉得自己不够洒脱,做不好取舍,总是想各方面都兼顾,结果哪方面都顾不好。所以还不如在自己喜欢的事情上全情投入,不去计较太多得失,反倒会更加心情愉快,做事情的结果也更好。
你可能会问,那这些极客都发展得怎么样呢?
我所认识的极客,有的是在小公司工作,有的是在大公司工作,还有的是在创业。不过,不管从事什么岗位,似乎都发展得不错。我想,这是因为他们从底层上选择了一个更好的发展逻辑:首先是做好取舍,让自己能够专注技术;在拥有了比较好的技术底蕴以后,他们也有更好的施展自己才华的平台;在专注于技术价值的同时,他们的生活也变得简单和健康。
OK讲完了搞技术的我再讲讲搞创业的朋友的故事以及他们给我的启迪。
## 创业者这个物种
我周围的朋友有不少是搞创业的。这些人往往都有一些很特别的点,让我欣赏、赞叹乃至仰慕。
首先一点,是**坚韧不拔的意志力**。
我们都知道,创业肯定不是简单的事情。而让一个企业能够穿越惊涛骇浪,最重要的就是创始人坚韧不拔的意志品质。
我本科的同班同学中,就有一个创业者,他公司的主营业务是户外运动用品,目前已经做到上市了。他的性格就很坚韧,我给你讲两个故事。
第一个在他成为我北大的同学之前其实曾经考上了一所技术类的军校。但后来他发现自己并不喜欢那里于是就想退学。可是军校岂可以当作儿戏想来就来想走就走为了能够退学他想了很多办法包括自己注射大剂量的抗生素产生精神恍惚的效果以便让校医诊断为精神疾病此法不成又从3楼的阳台上滚下来想把胳膊摔断以此理由退学……后来校领导实在看他态度坚决也就同意了他退学。他又重新参加了高考选择了他喜欢的学校和专业。
第二个大约在2006年我们一些同学因为毕业十周年又聚到了一起去内蒙古草原上玩其中一项活动就是骑马。我的这位同学骑术很好在草原上策马狂奔。不过在一个地方突然马失前蹄他从马背上摔了下来。这真是很惊险的一个意外我们在场一群人看了都心惊肉跳。不过他休息了一会以后又要了一匹马上马继续策马狂奔。晚上我们问他为什么刚摔了又骑他说如果今天不骑以后就不敢骑了。
说到这我想再多讲一个例子。这是我同一级的另一个同学的故事他是社会学系的。如果我说他的名字很多同学应该都会知道。他从2000年开始做一个与汽车有关的网站结果后来互联网泡沫破裂然后投资人撤资。他就自己筹了2000万买下了投资人的股份坚持做了下去直到2011年上市。想想看那个年头的2000万是多大的压力。但他就是咬着牙挺过来了。
我不知道有多少人能拥有像他们这样钢铁般的意志力。并且,令我沮丧的是,我怀疑这种个性可能主要是天生的?反正我是万万难以做到的。所以,创业这件事情,其实不是每个人都适合去做。而我这两个同学能做到上市,也绝不是偶然。
不过,为了不让自己的希望完全破灭,我还是倾向于相信意志和勇气这样的事情,至少在部分上是可以后天磨炼的。我在大学的时候练习过拳击,因为我觉得拳击可以锻炼人的勇气。来拳的时候不能眨眼,是拳击运动员的基本素质。那么在创业中,如果我们每次都去积极地面对挑战,那面对困难的能力也会越来越强。
我认识的其他几个创业者,虽然不像这两位那么夸张,但在意志力方面,也都属于罕见的。比如,某个技术社区,其创始人能够做到天天更新内容,十年如一日,这就是常人所不及的。最近我通过写编译原理的课程,也对内容编写这件事有了一定的体会。这样的事情,做一个星期、一个月、一个季度,是凭着兴趣和热情就可以做到的。而长年累月地去做,你要说没有意志力的因素,那是不可能的。
说完了强大的意志力,我再来说说我钦佩的这些人的第二点品质,就是**有主见,不从众**。
我观察,这些创业成功的人,往往判断事情都有自己的标准,这些标准往往与大众是不一致的。
还是说我同班的那个同学。在学校读书的时候,他经常就会消失不见了,过一阵再重新出现,他告诉我们,这次去陕北了,有什么感受,怎样怎样。过一段时间又会消失,回来后,说自己在新疆沙漠里独自走了几天,遇到被人追赶,差点殒命,等等等等。
等到快期末考试的时候他拉着我在未名湖边给他补习高数说能及格就行。几年以后在创业的过程中他还读了个清华的MBA班也是连毕业证都没要。按他的意思来说就是学到知识就行了。证书什么的不重要。
而我们这些俗人,天天使劲读书。等到毕业以后,又根据习惯和潮流,很多人又去出国,虽然我敢说,大部分同学那时候都想不清楚出国到底要干嘛。
所以从某种意义上来讲,比尔·盖茨、马克·扎克伯格等人敢于辍学创业,本身就意味着他们不是一般人。
而作为对比,还有一些人,都不管自己什么年纪了还在花高价去混文凭,不停地想往自己身上贴一些标签,来为自己壮胆。我觉得,这些人不要说创业了,给他一个重要的职位都是一件很冒险的事情。
前面我也提到了有些极客,会基于自己的兴趣爱好来创业。他们喜欢的技术和产品,往往在很长的时间内都不会得到社会的认可,不能变成有经济价值的商品。然而他们就是会坚持自己的方向。这些人,也是我学习的榜样。
这些技术创业者有的发展比较顺利但似乎也不是刻意为之。比如上海的小X我跟他在技术活动上有几面之缘。他搞了一个用于物联网的小小的OS搞了很多年了前两年突然听说融了很多资估值不错。我觉得资本投在这些人身上是投对了。
也有的朋友,会经历一些坎坷。但是他们总是按照自己的方式去折腾,保持对科技发展趋势的敏锐观察。每隔一段时间,我总能从他们那里听到一些新的思想和动态。就拿我一个做移动端底层平台朋友来说,他做这个方向已经很多年了。我相信他肯定会做成。不过先不说未来结果如何,至少我觉得他的生活状态是洒脱的、阳光的、不纠结的。
## 小结
今天的加餐,我给你分享了周围搞技术的和做创业的一些朋友的故事。这些故事跟你有什么关联呢?
首先,你选择了编译原理这门课程,基本上已经说明你有成为一名极客的潜质,否则也不会给自己这个挑战。但是在这个过程中呢,你可能会遇到很多的困难和心理上的纠结。我希望通过我分享的故事,能够帮助你做好取舍,丢掉包袱,健康阳光地拥抱作为一个技术从业者的职业生涯。
而如果你不小心选择了创业这条路,我也希望你能够像故事中的人物一样,去磨炼自己的意志力,以及坚持自己的主见。成功不成功不敢保证,至少你的生活会是很有价值的,不会后悔的。
以上也是对我自己的勉励,希望能跟你共勉。如果你或你身边也有类似的故事,欢迎在留言区分享出来。同样,也非常欢迎你把这一讲分享出去。
感谢你的阅读,我们结束语见!

View File

@@ -0,0 +1,278 @@
<audio id="audio" title="不定期加餐5 | 借助实例探究C++编译器的内部机制" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/30/34/30fc0f334fe58e3bdcee736fef24e234.mp3"></audio>
你好我是宫文学。欢迎来到编译原理实战课的加餐环节今天我们来探讨一下C++的编译器。
在前面的课程中我们已经一起解析了很多语言的编译器了但一直没有讨论C和C++的编译器。并不是因为它们不重要而是因为C语言家族的编译器实现起来要更复杂一些阅读代码的难度也更高一些会对初学者造成比较大的挑战。
不过没有解析C和C++语言的特性及其编译器的实现其实在我心里也多多少少有点遗憾因为C和C++是很经典的语言。至今为止,我们仍然有一些编程任务是很难用其他语言来代替的,比如,针对响应时间和内存访问量,需要做精确控制的高性能的服务端程序,以及一些系统级的编程任务,等等。
**C和C++有很多个编译器今天我们要研究的是Clang编译器**。其实它只是前端编译器而后端用的是LLVM。之所以选择Clang是因为它的模块划分更清晰更便于理解并且还可以跟课程里介绍过的LLVM后端工具串联起来学习。
另外因为C++语言的特性比较多编译器实现起来也比较复杂一些下手阅读编译器的源代码会让人觉得有点挑战。所以今天这一讲我的主要目的就是给你展示如何借助调试工具深入到Clang的内部去理解它的运行机制。
**我们会具体探究哪个特性呢我选择了C++的模板技术**。这个技术是很多人学习C++时感觉有困难的一个技术点。通过探究它在编译器中的实现过程你不仅会加深了解编译器是如何支持元编程的也能够加深对C++模板技术本身的了解。
那么下面我们就先来认识一下Clang这个前端。
## 认识Clang
Clang是LLVM的一个子项目它是C、C++和Objective-C的前端。在llvm.org的官方网站上你可以下载Clang+LLVM的源代码这次我用的是10.0.1版本。为了省事你可以下载带有全部子项目的代码这样就同时包含了LLVM和Clang。然后你可以参考官网的文档用Cmake编译一下。
我使用的命令如下,你可以参考:
```
cd llvm-project-10.0.1
#创建用于编译的目录
mkdir build
cd build
#生成用于编译的文件
cmake -DCMAKE_BUILD_TYPE=Debug -DLLVM_TARGETS_TO_BUILD=&quot;X86&quot; -DLLVM_BUILD_EXAMPLES=ON ../llvm
#调用底层的build工具去执行具体的build
cmake --build .
```
**这里你要注意的地方是我为Cmake提供的一些变量的值**。我让Cmake只为x86架构生成代码这样可以大大降低编译工作量也减少了对磁盘空间的占用并且我是编译成了**debug的版本**这样的话我就可以用LLDB或其他调试工具来跟踪Clang编译C++代码的过程。
编译完毕以后你要把llvm-project-10.0.1 /build/bin目录加到PATH中以便在命令行使用Clang和LLVM的各种工具。你可以写一个简单的C++程序比如说foo.cpp然后就可以用“clang++ foo.cpp”来编译这个程序。
>
<p>补充如果你像我一样是在macOS上编译C++程序并且使用了像iostream这样的标准库那么可能编译器会报找不到头文件的错误。这是我们经常会遇到的一个问题。<br>
&nbsp;<br>
这个时候你需要安装Xcode的命令行工具。甚至还要像我一样在.zshrc文件中设置两个环境变量</p>
```
export CPLUS_INCLUDE_PATH=&quot;/Library/Developer/CommandLineTools/usr/include/c++/v1:$CPLUS_INCLUDE_PATH&quot;
export SDKROOT=&quot;/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk&quot;
```
到目前为止你就把Clang的环境配置好了。那回过头来你可以先去看看Clang的源代码结构。
你会看到,**Clang的源代码主要分为两个部分**:头文件(.h文件全部放在include目录下而.cpp文件则都放在了lib目录下。这两个目录下的子目录结构是一致的每个子目录代表了一个模块模块的划分还是很清晰的。比如
- AST目录包含了AST的数据结构以及对AST进行遍历处理的功能。
- Lex目录词法分析功能。
- Parse目录语法分析功能。
- Sema目录语义分析功能Sema是Sematic Analysis的缩写
接下来你可以进入这些目录去寻找一下词法分析、语法分析、语义分析等功能的实现。由于Clang的代码组织很清晰你可以很轻松地根据源代码的名称猜到它的功能从而找到语法分析等功能的具体实现。
现在,你可以先猜测一下,**Clang的词法分析和语法分析都是如何实现的呢**
如果你已经学过了第二个模块中几个编译器的实现可能就会猜测得非常准确因为你已经在Java编译器、Go的编译器、V8的编译器中多次见到了这种实现思路
- **词法分析:**手写的词法分析器,也就是用手工的方法构造有限自动机。
- **语法分析:**总体上,采用了手写的递归下降解析器;在表达式解析部分,采用的是运算符优先级解析器。
所以,针对词法分析和语法分析的内容,我们就不多展开了。
那么,**Clang的语义分析有什么特点呢**
通过前面课程的学习现在你已经知道语义分析首先要做的是建立符号表并做引用消解。C和C++在这方面的实现比较简单。简单在哪里呢?因为它**要求必须声明在前,使用在后**,这就让引用消解变得很简单。
而更现代一些的语言在声明和使用的顺序上可以更加自由比如Java类中方法中可以引用类成员变量和其他方法而被引用的成员变量和方法可以在该方法之后声明。这种情况对引用消解算法的要求就要更高一些。
然后现在你也知道在语义分析阶段编译器还要做类型检查、类型推导和其他很多的语义检查。这些方面Clang实现得也很清晰你可以去看它的StaticAnalysis模块。
最后在语义分析阶段Clang还会做一些更加复杂的工作比如C++的模板元编程机制。
我在[探究元编程](https://time.geekbang.org/column/article/282919)的那一讲中介绍过C++的模板机制它能有效地提高代码的复用能力。比如你可以实现一个树的容器类用来保存整型、浮点型等各种不同类型的数据并且它不会像Java的泛型那样浪费额外的存储空间。因为C++的模板机制,会根据不同的模板类型生成不同的代码。
**那么C++具体是如何实现这一套机制的呢**?接下来我就带你一起去深入了解一下,从而让你对模板元编程技术的理解也更加深入。
## 揭秘模板的实现机制
首先我们通过一个示例程序来观察一下Clang是如何编译模板程序的。假设你写了一个简单的函数min用来比较两个参数的大小并返回比较小的那个参数。
```
int min(float a, float b){
return a&lt;b ? a : b;
}
```
你可以用clang++命令带上“-ast-dump”参数来编译这个示例程序并显示编译后产生的AST。
```
clang++ -Xclang -ast-dump min.cpp
```
下图中展示的是min函数对应的AST。你能发现AST节点的命名都很直观一下子就能看明白每个节点的含义。其中函数声明的节点是FunctionDecl也就是Function Declaration的缩写。
<img src="https://static001.geekbang.org/resource/image/50/a8/50e994b96ef6fbc57f8afd0969yy6ba8.jpg" alt="">
min函数是一个普通的函数只适用于参数为浮点型的情况。那么我们再增加一个使用模板的版本并且函数名称一样这样就可以支持用多种数据类型来比较大小比如整型、双精度型等。
```
template &lt;typename T&gt; T min(T a, T b){
return a&lt;b ? a : b;
}
```
这时顶层的AST节点是FunctionTemplateDecl也就是函数模板声明。它有两个子节点一个是模板类型参数声明TemplateTypeParmDecl也就是尖括号里面的部分第二个子节点其实是一个普通的函数声明节点其AST的结构几乎跟普通的min函数版本是一样的。
<img src="https://static001.geekbang.org/resource/image/a6/51/a65d293573d52eyy6b69894dbda6f851.jpg" alt="">
这样通过查看AST你就能了解函数模板和普通函数的联系和区别了。接下来就要进入重点了**函数模板是如何变成一个具体的函数的?**
为此我们在main函数里调用一下min函数并传入两个整型的参数min(2,3)
```
int main(){
min(2,3);
}
```
这个时候我们再看一下它生成的AST就会发现函数模板声明之下增加了一个新的函数声明。这个函数的名称仍然是min但是参数类型具体化了是整型。
<img src="https://static001.geekbang.org/resource/image/f9/39/f9b26cbab65beca0eab565cdfcf93c39.jpg" alt="">
这说明当编译器发现有一个min(2,3)这样的函数调用的时候,就会根据参数的类型,在函数模板的基础上生成一个参数类型确定的函数,然后编译成目标代码。**这个过程叫做特化Specialization也就是从一般到具体的过程。**函数模板可以支持各种类型,而特化后的版本只针对某个具体的数据类型。
那么特化过程是怎样发生的呢我们目前只看到了ASTAST反映了编译的结果但它并没有揭示编译的过程。而只有搞清楚这个过程我们才能真正理解模板函数的编译机制。
**要揭示编译过程,最快的方法是用调试器来跟踪程序的执行过程。**最常用的调试器就是LLDB和GDB。这里我使用的是LLDB你可以参考我给出的命令来设置断点、调试程序。
<img src="https://static001.geekbang.org/resource/image/11/71/117d0c937bd8c0dacdf1f98f2b54d671.jpg" alt="">
>
小提示如果你像我一样是在macOS中运行LLDB可能会遇到报错信息即操作系统不让LLDB附加到被调试的程序上。这是出于安全上的考虑。你需要重启macOS并在启动时按住command-R键进入系统恢复界面然后在命令行窗口里输入“csrutil disable”来关闭这个安全选项。
不过在跟踪clang++执行的时候你会发现clang++只是一个壳真正的编译工作不是在这个可执行文件里完成的。实际上clang++启动了一个子进程来完成编译工作这个子进程执行的是clang-10。所以你需要另外启动一个LLDB来调试新启动的进程。
<img src="https://static001.geekbang.org/resource/image/03/27/03b9199c070ea23955493f331bcc8927.jpg" alt="">
在使用LLDB的时候你会发现确定好在什么位置上设置断点是特别重要的这能大大节省单步跟踪所花费的时间。
**那么现在,我们想要探究函数模板是什么时候被特化的,应该在哪里设置断点呢?**
在研究前面示例程序的AST的时候我们发现编译器会在函数特化的时候创建一棵新的函数声明的子树这就需要建立一个新的FunctionDecl节点。因此我们可以监控FunctionDecl的构建函数都是什么时候被调用的就可以快速得到整个调用过程。
那怎么查看调用过程呢当clang-10在FunctionDecl断点停下以后你可以用“bt”命令打印出调用栈。我把这个调用栈整理了一下并加了注释你可以很容易看清楚编译器的运行过程
<img src="https://static001.geekbang.org/resource/image/bb/1b/bb0afc7e0e9ab5d4b2021d3cc0b6301b.jpg" alt="" title="图1模板函数特化时的调用栈">
接着,分析这个调用栈,你会发现其主要的处理过程是这样的:
- 第一语法分析器在解析表达式“min(2,3)”的时候会去做引用消解弄清楚这个min()函数是在哪里定义的。在这里,你又一次看到语法分析和语义分析交错起来的情况。在这个点上,编译器并没有做完所有的语法分析工作,但是语义分析的功能会被按需调用。
- 第二,由于函数允许重载,所以编译器会在所有可能的重载函数中,去匹配参数类型正确的那个。
- 第三编译器没有找到与参数类型相匹配的普通函数于是就去函数模板中找结果找到了以T作为类型参数的函数模板。
- 第四根据min(2,3)中参数的类型对函数模板的类型参数进行推导结果推导出T应该是整型。这里你要注意min(2,3)的第一个参数和第二个参数的类型需要是一样的,这样才能推导出正确的模板参数。如果一个是整型,一个是浮点型,那么类型推导就会失败。
- 最后,把推导出来的类型,也就是整型,去替换函数模板中的类型参数,就得到了一个新的函数定义。不过在这里,编译器只生成了函数声明的节点,缺少函数体,是个空壳子。
注意,这里最后一句的说法只是目前我自己的判断,所以我们要来验证一下。
Clang在重要的数据结构中都有dump()函数AST节点也有这个函数。因此你可以在LLDB中调用dump()函数来显示一棵AST子树的信息。
```
(lldb) expr Function-&gt;dump()
```
这个时候在父进程的LLDB窗口中会显示出被dump出的信息输出格式跟我们在编译的时候使用-ast-dump参数显示的AST是一样的。从输出的信息中你会看到当前的函数声明是缺少函数体的。
<img src="https://static001.geekbang.org/resource/image/12/72/12b70df96e84a6f55a0fdbb0cdd6d372.jpg" alt="">
**那么,函数体是什么时候被添加进来的呢?**这个也不难,你仍然可以用调试器来找到答案。
从前面函数模板的AST中你已经知道函数体中包含了一个ConditionalOperator节点。所以我们可以故技重施在ConditionalOperator()上设置断点来等着。因为编译器要实例化函数体就一定会新创建一个ConditionalOperator节点。
事实证明,这个策略是成功的。程序会按照你的预期在这个断点停下,然后你会得到下面的调用栈:
<img src="https://static001.geekbang.org/resource/image/4c/a5/4c86365e55460021fc40b5d005c41aa5.jpg" alt="" title="图2创建函数体的过程">
研究这个调用栈,你会得到两个信息:
1. 从函数模板实例化出具体的函数是被延后执行的程序是在即将解析完毕AST之后才去执行这项任务的。
1. Clang使用了TreeTransform这样的工具类自顶向下地遍历一棵子树来完成对AST的变换。
这样经过上述处理以后函数的特化才算最终完成。这个时候你再dump一下这个函数声明节点的信息就会发现它已经是一个完整的函数声明了。
好了到此为止你就知道了Clang对函数模板的处理过程。我再给你强调一下其中的关键步骤你需要好好掌握
- 在处理函数调用时,要去消解函数的引用,找到这个函数的定义;
- 如果有多个重载的函数,需要找到参数类型匹配的那个;
- 如果找不到符合条件的普通函数,那就去找函数模板;
- 找到函数模板后,推导出模板参数,也就是正确的数据类型;
- 之后,根据推导出的模板参数来生成一个具体的函数声明。
**其中的关键点,是特化的过程。编译器总是要把模板做特化处理,然后才能被程序的其他部分使用。**
抓住了这个关键点你还可以进一步在大脑中推演一下编译器是如何处理类模板的。然后你可以通过打印AST和跟踪执行这两个技术手段来验证你的想法。
不过,模板技术可不仅仅能够支持函数模板和类模板,它还有很多其他的能力。比如,在[第36讲](https://time.geekbang.org/column/article/282919)我介绍元编程的时候,曾经举过一个计算阶乘的例子。在那个例子中,模板参数不是类型,而是一个整数,这样程序就可以在编译期实现对阶乘值的计算。
好了,现在你已经知道,**对于类型参数,编译器的主要工作是进行类型推导和特化**。
**那么针对非类型参数,编译器是如何处理的呢?**如何完成编译期的计算功能的呢?接下来,我们就一起来分析一下。
## 使用非类型模板参数
首先,你可以看看我新提供的这个示例程序,这个程序同样使用了模板技术,来计算阶乘值。
```
template&lt;int n&gt;
struct Fact {
static const int value = n*Fact&lt;n-1&gt;::value; //递归计算
};
template&lt;&gt;
struct Fact&lt;1&gt; {
static const int value =1; //当参数为1时阶乘值是1
};
int main(){
int a = Fact&lt;3&gt;::value; //在编译期就计算出阶乘值
}
```
在Fact这个结构体中value是一个静态的常量。在运行时你可以用Fact&lt;3&gt;::value这样的表达式直接使用一个阶乘值不需要进行计算。而这个值其实是在编译期计算出来的。
**那编译期具体的计算过程是怎样的呢?**你可以像我们在前面研究函数模板那样如法炮制,马上就能探究清楚。
比如你可以先看一下示例程序在编译过程中形成的AST我在其中做了一些标注方便你理解
<img src="https://static001.geekbang.org/resource/image/7a/d6/7a1884bd2b01ccf65c42e80acc55ecd6.jpg" alt=""><img src="https://static001.geekbang.org/resource/image/66/dd/66376b3d937aeba74e7bf33b6ba94fdd.jpg" alt="">
可以看到在AST中首先声明了一个结构体的模板其AST节点的类型是ClassTemplateDecl。
接着是针对这个模板做的特化。由于在main函数中引用了Fact&lt;3&gt;::value所以编译器必须把Fact&lt;3&gt;特化。特化的结果是生成了一棵ClassTemplateSpecializationDecl子树此时模板参数为3。而这个特化版本又引用了Fact&lt;2&gt;::value。
那么编译器需要再把Fact&lt;2&gt;特化。进一步这个特化版本又引用了Fact&lt;1&gt;::value。
而Fact&lt;1&gt;这个特化版本在程序中就已经提供了它的value字段的值是常数1。
那么经过这个分析过程Fact&lt;3&gt;的值就可以递归地计算出来了。如果`Fact&lt;n&gt;`n的值更大那计算过程也是一样的。
```
Fact&lt;3&gt;::value = 3 * Fact&lt;2&gt;::value
= 3 * 2 * Fact&lt;1&gt;::value
= 3 * 2 * 1
```
另外你还可以用这节课中学到的debug方法跟踪一下上述过程验证一下你的想法。在这个过程中你仍然要注意设置最合适的断点。
## 课程小结
今天我们一起探讨了C++的模板机制的部分功能并借此了解了Clang编译C++程序的机制。通过这节课你会发现编译器是通过特化的机制来生成新的AST子树也就是生成新的程序从而支持模板机制的。另外你还要明确特化的过程是递归的直到不再有特化任务为止。
模板功能是一个比较复杂的功能。而你发现,当你有能力进到编译器的内部时,你会更快、更深刻地掌握模板功能的实质。这也是编译原理知识对于学习编程的帮助。
探究C++的编译器是一项有点挑战的工作。所以在这节课里我更关注的是如何带你突破障碍掌握探究Clang编译器的方法。这节课我只带你涉及了Clang编译器一个方面的功能你可以用这节课教给你的方法继续去探究你关心的其他特性是如何实现的可能会有很多惊喜的发现呢
## 一课一思
在计算阶乘的示例程序中当n是正整数时都是能够正常编译的。而当n是0或者负数时是不能正常编译的。你能否探究一下编译器是如何发现和处理这种类型的编译错误的呢
欢迎在留言区分享你的发现。如果你使用这节课的方法探究了C++编译器的其他特性,也欢迎你分享出来。