乐趣区

教你用认知和人性来做最棒的程序员

不久前,在团队内部和大家做了一次分享,内容就是这次要讲的“用认知和人性来提升自己的技术水平”,大家反响不错,所以这次整理一下也分享给大家。最初我是想用“借优秀的产品经理思维来做最棒程序员”的这个标题,但想想还是要有同理心,技术同学平时和产品同学已经是相爱相杀了,就不刺激大家啦。但是必须要说的是优秀的产品经理思维和优秀的程序员思维确实是殊途同归的,两者是想通的,就是来自认知和人性。
这里我不会过多去梳理认知和人性的概念,后面会用很多例子来说明,保证通俗易懂,只想先提 2 个概念:

对人性的理解能帮助提升认知
狭义的技术是指 java,php,android,spring,vue 等的掌握和实践,它们只是帮助你提升认知的工具,却绝不等同于认知。

下面我来逐一举例说明
例子 1 - 技术选型

问题:今年开始慢慢火的一个移动端跨平台技术是 google 发布的 ”flutter”,如果你作为一名移动端的开发人员来评估这门技术是否值得选型作为公司产品的语言框架,你怎么能保证评估不会看走眼?

认知:flutter 强化了跨平台的生产效率,且性能比前端框架更好。

解释:很多同学会想,怎么第一句感觉就像废话一样,人家官方文档也是这么写的,这叫什么认知。别急,所谓的认知,就是能够提炼成外人看上去貌似一句很普通的话,但只有经过深度思考的你才知道它真正的价值。在 flutter 没有出现前,我存在一个认知偏差,我认为客户端一定会被前端诸如 react,vue 这样的技术取代。因为它们既可以跨平台,也可以随时更新,符合互联网快速变化的节奏。但我的认知存在一个非常严重的漏洞,那就是跨平台和随时更新在客户端技术里的占比各应该是多少?哪个更重要?经过分析思考,以我们公司当前用户量的发展阶段,提升跨平台的生产效率且不损失太多性能更重要,所谓的运营快速需求变化有时候可以通过事先想清楚,而降低频率。

flutter 带来的生产效率提升,不仅仅是一个开发可以同时产出 android 和 ios 两端应用。更在于产品经理以后只需要和一个开发沟通需求细节,不会再担心出现 android 和 ios 功能细节实现偏差的问题了。由于有了这样的认知,虽然 flutter 作为新技术,还有需要完善的地方。但这不是主要问题,我们愿意为它去冒险,在我们的产品里去尽快实践。

人性:最后多说一句,为什么 google 先做了 kotlin 后又做了 flutter 呢?我的认知是:大公司两个部门做重复轮子很正常,互相竞争,看谁更好。一个想试探性取代 java 以避免被 oracle 捏住命脉(如果接受的人多,将来把底层的 jvm 再抽掉),一个野心更大希望统一所有平台,不同部门的想法而已。大家不要把 google 的布局想得那么纯粹技术化,大家都是人嘛。人脱离不了:竞争,征服,自保的人性。:)
例子 2 - 查线上问题

问题:觉得查线上问题很痛苦,压力很大,查得也不快怎么办?

认知:1 查线上问题是成本最小的,锻炼逻辑思维的方式,相比写代码更有效率。2 查问题要看本质,抓住案发第一现场

解释:很多同学碰到线上问题的时候,都很痛苦,因为要加班了耽误我学习技术的时间,所以有时查问题态度也不积极。这个认知是非常错误的,大家平时都会认可优秀程序员的核心特质看的是思维逻辑,而不是用哪个语言哪个技术。那如果是思维逻辑优先,写代码就能比查线上问题更能提升吗?显然不是,大家知道我们在写代码时,往往要花费很多时间在编写冗余代码(如 get,set 代码,配置文件),普通的 crud 逻辑,编译,部署等这些非核心点上,它们并不能帮助我们提升思维(动手写代码前的思考才是最核心的)。但是查线上问题就不一样了,你不需要写任何代码,但是需要在很短时间内,让自己理清思路,按正确的步骤去查出代码的核心问题,底层系统的核心问题。你需要对系统很了解,对业务逻辑很了解,对代码细节很了解,这真是一个几乎没有任何冗余步骤,但是却能快速提升严谨思维的好方式!

怎么让查问题更有效率?其实很简单,我们如果借鉴名侦探柯南的想法,那就是“抓住案发第一现场”。举两个例子,对于 JAVA 这样的静态语言,查询线上日志的方法是非常重要的。很多同学发现某个请求出问题了,就去看当次请求的日志,这种方式不一定准确。因为对于静态语言,它的案发第一现场可能已经不是当次请求了,很有可能是首次发生这个问题的时候,或者服务器刚刚启动的时候(静态语言的”缓存”特色)。当你发现上层的业务系统发生了 mysql 死锁的报错,就不要太纠结于上层业务系统的日志了。应该去看 mysql 的 bin log,抓住这个案发第一现场,看看到底发生了什么。不知道怎么解决线上问题,99% 是因为连案发第一现场都没找到,等你找到了,基本也有解决方法了。

人性:每个人都喜欢做省力的事情,喜欢的事情。但是人往往有偏见,根本没有想明白查线上问题的价值,就认为这是一个很 low 的事,是不可取的。对自己不了解的,未知的事物,应该敬畏和学习。
例子 3 - 技术面试

问题:很多同学的技术经验已经很扎实了,也能写出很稳定的代码,但是作为技术面试官,为什么老是会看走眼呢?

认知:对应聘者而言,能否独立解决问题是能通过面试的及格线,应聘者专业技术的掌握程度只决定 offer 薪资的高低。

解释:是不是觉得又来歪论拉?恩,继续解释一番。首先问你,你为什么要招人,我想信很多人都会这么说:当然是找你来帮我干活啊,我现在天天干到 11 点,累死了,急需人帮忙啊。恩,所以你很清楚,这个人是要能独立解决问题的,能帮你分担的,不是来了还要你天天在那里盯着的。但是我们看到很多同学的内心认知是混乱的,虽然他能看懂这句话,但是在面试的时候他会这么做:准备 10 个左右他擅长的技术细节问题,一个个问,应聘者只能答出 5 个,废柴,不送。答出 7 个,恩,可以进来。答出 10 个,还说了 1 个我不知道的,好牛逼,绝不能让他看出来我比他弱,否则进来后还怎么带他。但是这个和你之前痛恨的应试教育又有什么区别呢?这种招聘方式有很大的风险招进来的人是研究手机屏幕从几楼摔下去不会碎,而不是研究让屏幕显示更清晰的人。

正确的方式应该是:让他讲一个之前投入度比较高的项目,描述下自己是怎么独立去解决问题的。对每一个点的描述,只要你觉得还不能体现他“独立解决问题”的能力,那就继续扒皮深问,直到他竭尽全力,被你”逼到墙角”。特别优秀的人被逼到墙角后,具备现场把墙砸掉的能力,这样的人是死也不能放过的,具体什么意思大家可以去体会思考。之前我们曾经面试过一个性能测试工程师,从技术细节看对性能测试的工具和方法是比较了解的。在项目描述中我们问了他一个问题:你之前通过性能压测发现的服务端问题,有去了解过发生的原因吗?他给的答复是:因为我们是外企,制度比较明确,开发也是另外一个部门,所以我没有去了解。不好意思,这个回答基本体现了没有独立解决问题的能力乃至意识。碰到一堵很小的墙,他都没有办法独立解决,好奇和学习的欲望也很弱。他在技术细节上的积累只是因为看了几本书,用了几次工具,这些都只是为了应付面试和不懂的领导,根本没有深入实践,他未来的瓶颈一定非常大。只要能够独立解决问题,就一定能通过面试,有些技术不了解,最多就是被砍点薪资而已。在这一点上,10 年工作经验的同学还真未必比得上 2 - 3 年工作经验的同学,如果没有独立解决问题的能力,那只是多累积了一些所谓的专业经验,但还是无法解决问题。很多大公司喜欢校招优秀的毕业生,也是这个原因,虽然这些学生还没有实际工作过,但已经具备了很强的独立解决问题能力。我们曾经招过一名同济大学的测试实习生,有一次她独立组织了部门的团建活动,搞得井井有条,方方面面都考虑到了,这样的同学做好技术只是时间问题。:)

人性:应聘者的人性有哪些呢?懒:影响独立解决问题的意识。要面子:比如刚刚举的例子,拿公司制度掩盖自己无法独立解决问题的现状。(并且他自己是意识不到的,因为他内心的认知是混乱的)盲目自信又不自信:对自己做的熟的东西盲目自信,对没接触过的技术很不自信。
例子 4 - 最严重的线上故障

问题:到底是什么原因,会导致严重的线上故障呢?是我们团队的技术水平不高,还是流程问题才造成了如此严重的故障呢?

认知:个体的过失很难造成严重的线上故障。真正的原因是:集体性的认知出错。

解释:在现代微服务的架构下,各服务之间的解耦性已经做得非常好了,总体来说出现全面严重问题的概率已经降得非常多了。就像一个国家一样,不怕局部的腐败,怕的是整个链条的腐败。举个例子,如果一个系统上线前,需要在数据库里配置一个关键的参数,如果不配置会导致很多请求处理错误。但是开发同学发生了错误的认知,潜意识里认为配置不是写代码 = 配置没有写代码技术含量高 = 配置没有写代码重要,最后把它忘了。测试同学认为测试配置不是测试新写的代码 = 优先测试新写的代码,再测试配置 = 测试代码比测试配置更重要,最后把它也忘了。那这基本上是救不回来了,上线后一定会发生严重的问题,每个链条的检查机制都失灵了。坚决预防集体性的认知出错,就可以避免很多严重的问题。

集体性的认知出错往往是从一些小现象开始的,比如我们的团队曾经发生过一次正常的项目延期,原因是周五到了,没有完成测试,为了避免仓促上线出问题,所以延期一天发布。其实到这里都是非常正常的,但是当测试同学在钉钉群里发出这个原因的时候,有一些同学发出了大拇指的表情。注意,这个时候大家是没有犯错的,但是认知已经出现了偏差,变成了“以后就算测不完,只要说项目风险,就可以延期”。群里很多同学都看着,一旦这个集体性的认知偏差形成,未来项目的延期就会越来越多。所以需要立刻出来说一句:因为风险项目暂时不上可以,但是延期的原因要总结反思。通过这样一句让大家心里不太舒服的话,尽快把集体性认知偏差扭转过来。马云说过”小事要大做”,就是这个道理,不大做,等发生大事的时候就来不及了。

人性:盲目自信:对自己做的领域有天然的偏见,哪个重要,哪个不重要。随大流:别人也这么做了,应该不会错,还省力,我也这么做。懒:默守所谓的安全方案,其实在那个场景下已经不安全了,但是内心认知出现偏差,懒得去破局改进。
例子 5 - 如何看待代码逻辑复用

问题:对于代码逻辑的复用,大家的看法往往不一样,有些同学认为只要是有公共性的代码都该不断抽出通用函数复用。有些则认为对重要的通用逻辑才该复用,过度复用反而增加成本。

认知:能力该复用,业务不该复用。分久必合,合久必分。

解释:这里提出了两个认知,我们来分别解释下。能力该复用,业务不该复用,这个很好理解。能力是指对这个系统有价值的功能,会长期存在且扩展下去的。而业务是一个泛指,既可以表示单一的产品需求,也可以表示某个局部的功能。比如你的应用里接入了一个支付宝支付,对支付这个事情我们判断下来是一个基础核心能力,且将来很有可能也要接入微信支付,所以应该抽出公共的函数。再比如对于客户端的登录页面和注册页面,虽然渲染逻辑 90% 是一样的,但是不应该复用,因为它们是单一功能,不是能力,贸然复用反而带来了很大的风险。

分久必合,合久必分,这个的理解就很有意思了。大家都知道,这句话的出处来自三国演义,说的是一个国家分裂久了就会合并,合并久了也会分裂,其实对代码逻辑的复用也是如此。大家在合并抽出公共函数时,会发现有 10%-20% 的逻辑不是那么顺眼,总感觉暂时放在里面是可以的,但将来可能会拆出来。那么在写公共函数时,就要特别注意这部分逻辑。它虽然暂时在函数里,但是需要做到和上下文相对隔离,甚至还可以加入明显的换行和 TO DO,为下一次的拆做好准备。而在拆出一些独立逻辑的时候,也要思考这些逻辑可能和其它的哪些逻辑有机会是合起来的,那么尽量放在一个类里,一个包里,为后续的合做好准备。

人性:不要刻舟求剑,妄图用一套规则来应对外部复杂变化的世界,要因地制宜,实事求是,学会变通。
例子 6 - 开源的意义

问题:为什么现在很多中国的互联网公司开始重视开源的宣传了?

认知:开源直接决定了公司的成本收入,以及人才储备

解释:是不是要崩溃了,开源无偿写代码,然后免费给别人用,不是在消耗公司成本吗?别急,还记得马云说过的一句话吗,“免费的才是最贵的”。恩,这个道理同样适用于开源。今天中国很多的互联网公司已经非常明白了,甭管你的开源技术到底好不好用,宣传一定要大,一定要让大家参与进来。

带来的好处太多了,因为用了你的开源消息队列,之后就会用你的云计算平台。因为程序员都很懒,开发环境和线上保持一套嘛,你后面一定能赚大钱。因为开源项目非常知名,让你公司的技术形象立刻高大起来(先不管这个项目到底创造了多少有价值的产品),每年校招的优质学生资源尽收囊中,其他公司要抢人,只能花更多的钱。而每年中国优秀的毕业生就那么多,早就供需失衡,谁抢到了大部分,那之后在技术上一定能保持绝对优势。最后万一公司财报不好看了,不好意思开始收授权费,就像 google 收 android 的费用一样。不作恶只是口号,开源带来了无比巨大的利益,不能赚钱,谁开源?!现在微软也懂了这个道理,成为了开源社区的标杆,但在早期的鲍尔默时代可是出现了认知偏差呢。

人性:开源者的人性:追求利益,喜欢声誉。接受开源的人:渴望进步,赚便宜,崇拜权威。
关键点:如何提升认知

内心简单:
内心越简单的人,将来能到达的境界就越高。大家千万不要误解了,我说的不是思想浅薄,而是内心简单纯粹要像少年一样。一个很好的例子,郭靖,用世俗的眼光来看他天资不高,开始学什么都慢。但是他有一个很大的优点,就是想法简单,无私心,持之以恒。报家仇,报国仇,保护好他爱的人,不会去想是不是别人骗了他,他多做一点是不是亏了。20 岁就达到五绝水平,最后终于融合“降龙十八掌”、“九阴真经”和“左右互搏”三大盖世武功为一体,武林尊为“天下第一侠士”。内心越简单,就越不会花费额外的精力在一些无关紧要的事上面。随着时间的推移,你的认知水平就一定能提升得更快。不要去想今天你学的语言明天是否还流行,先利用当前语言训练好你的思维模式。不要去想我作为测试给开发指出太多问题后,开发会不会不爽,做为测试你的核心是保证产品质量。不要去想今天我帮组内的开发分担了额外的代码编写,我是不是亏了,这些付出一定会在将来某个时候兑现,因为你比他们有更多的代码实践。

相信跨界的力量:
ipod+ 手机诞生了 iphone,手机 + 钱包诞生了支付宝,c,python+java 诞生了 go,人类的创新其实都是来自于跨界的结合。很多时候大家去看一个技术大神,会认为他一定是看了很多专业的书,看了很多牛逼开源项目的代码,写了很多项目才达到现在的这个水平。然后又看到别人的兴趣爱好:音乐,滑雪,画画,牛逼,大神就是大神,做好技术的同时还能“兼顾”这些兴趣。这个认知完全错了好吗,我告诉你,写代码看书固然很重要,但如果他没有这些兴趣,他在技术上可能根本达不到今天的程度。一个有画画功底的人,理解向量,理解数据的 PCA 分析就是快好吗。一个财务出身的人,写支付系统的代码就是不容易出错好吗。人类的大脑从来都是一个网状的,互相关联的知识图谱,根本不存在靠”单一事物”修炼成功的好吗。千万不要成为技术上的孔乙己,天天学各种 API 的写法,和学习茴香豆的茴字有几种写法没有任何区别。在方案想不出来的时候,在代码水平感觉到瓶颈的时候,在看不懂一些专业书籍的时候,一定要跳出来,和自己的兴趣结合,和自己经历结合,和自己的生活结合,这样才能突破瓶颈,提升到更上一层的认知。

相信更高认知人的指引:
科幻神作三体里,外星人看地球人就像纸片一样,在三体人的眼中,地球人是二维的,而不是三维的。回到现实中,高认知的人看低认知的人也是一样的,不是低认知的人不够努力,而是你的知识图谱里比高认知的人少了一些维度。所以不管你怎么努力,你会发现仍旧无法超过他,他还比你轻松,学霸给大家留下的阴影就是这么来的。在实际工作中,你的 leader,你的架构师只要不是水货,往往他们的认知就是比你高的。一旦你觉得这个人的本性是靠谱的,你就该无条件去相信他给你的建议和指引。因为他能看到在你那个维度上感受不到的东西,照他的话去实践几次,你才有机会到达他那个维度,才能升级认知。不过在现实情况中,我们往往看到很多 leader 和架构给下面的同学苦口婆心说了很多,但是他们不理解,反而更叛逆。这份痛苦我懂,你是拼了命想拉他到你那个维度,但是他还年轻着呢。:)

持之以恒地实践:
人就是一个如此奇妙,如此复杂的生物,不管你看多少书,看多少源码,写多少 demo,你不真刀真枪地去实践,去写代码,这些知识无论如何都无法进入你大脑的知识图谱。它们永远只能是“狭义上的知识”,而不是“有价值的认知”。相信大家人生中都有过类似的经历了,越是辛苦的实践,越是坚持,你最后的收获一定越大。简单来说,认知不通过持之以恒的实践是不可能升级的。还有一点我必须要强调,实践应该尽量和公司的项目去结合,而不是依靠于自己写 demo。这里面有一个很大的误区,自己私下写 demo 经常是没有“明确,高压的”目标的(人性总是偏懒的),这种实践往往很难提升认知。而公司的项目往往不同,会提出 ” 支持多少用户访问 ”,“为什么你每次开发都不能更快一点”(核心挑战的是你架构的扩展能力),“为什么这个功能这么卡”(性能优化),这些“明确的,高压的”目标能督促你去拼命提升自己的认知(只是写 demo 是很难给自己设下这些障碍的,是反人性的)。当然从结果来看,又是公司的压榨剥削拉,让我们回忆一下前面说的,如果你觉得这个公司是靠谱的,那就让我们的“内心简单一点”,持之以恒地实践升级认知吧。:)
最后总结一下,现在已经不是一个单纯比拼知识量的时代,而是比拼认知高低的时代。作为程序员我们并不特殊,和市场,财务,产品,运营的这些同学一样,核心看的是认知,并不存在谁比谁困难,谁比谁辛苦的这种浅层比较。而我们学习的那些语言,框架,工具,和我们大学时期学习的微积分,高等物理没有区别,都只是帮助我们不断训练提升认知的实践工具,而不是认知本身。让我们不要再局限于程序员狭义技术的范畴内,把提升自己的认知作为最重要的目标,我们要努力做到“既是程序员,也不是程序员”。

退出移动版