作者介绍
findyi,腾讯、360码农,前哒哒少儿英语技术VP,现任土豆教育CTO。
几周前,微盟爆了个大雷,数据库让内部员工删库跑路。写了篇文章,做了一些我的判断:从微盟36小时故障,谈谈数据安全这点事。
很明显,微盟的技术体系是有严重问题的,主要体现在:运维权限管理、数据库备份、上云而不上云方案,这三点。看起来有点耸人听闻,其实你永远不知道一个人或者一家公司的技术会低到什么程度,不少人可能从来都没用过GitHub和GitLab。
程序员这个行业,是一个区隔度特别高的行业。不少人短短几年就可以成长为高级工程师、资深架构师、首席架构师,而另外一部分人很可能工作10年还是初中级工程师。
程序员行业还有一个特点,优秀程序员的产出是普通程序员的好多倍,甚至是10倍!这是因为编程不是一门「线性科学」,而是一门「非线性科学」。
「线性科学」,比如跑步的速度就是,世界冠军的速度也不可能是普通人的10倍。「非线性科学」是指很多种因素交汇在一起,极大增加了系统的复杂度。
程序设计和实现不是一种线性能力,像经验、编码能力、工程能力、知识、学习新知识的能力、对无用部分的识别等这些就不仅仅是线性优势,汇聚到一起会对编程产生倍增级效应。
优秀的程序员能达到百万年薪,而入门级或者初中级程序员可能只能拿10万年薪。输出的10倍差距带来的是收入上的10倍差距!
很多时候,遇见复杂系统问题,派多少个初中级工程师都于事无补,而一个资深架构师就可以轻松搞定。
过去11年的职场生涯,我带过过百名程序员,见过非常优秀的也见过平庸的。以下是我认为程序员和普通程序员拉开巨大差距的7个关键点:
— 1 —
裸编程能力
裸编程能力:处理程序实际实现部分的子任务,实现函数或者算法之类的能力。听起来很简单对吧?实际上很多程序员缺失这样的能力。
不知道大家有没有见过「复制粘贴工程师」,review他们的代码甚至会发现一些网上的注释,又或者其他人的编写错误。
并不是所有程序员都具备利用必备的基本编程结构有效的实现某个产品或者某个模块。
不少工作多年的程序员甚至连一个简单算法排序都没有考虑,当然这并不影响普通工作的输出,但在面临调优或者攻坚,这类型的程序员的表现甚至比刚毕业的优秀程序员还要糟糕。
在工作中遇到过一次将代码时间复杂度降低几个数量级的情况,在压测模拟过万人同时使用的情况下,没优化前服务端程序直接卡死,优化后能流畅的运行。
在这个复盘过程中,我发现实现这个功能的程序员缺乏基础的算法基础。for循环的嵌套,简直是触目惊心。
BAT大厂招聘高级工程师,为什么总是要求手写各种算法,恐怕也是基于考察裸编程能力。
— 2 —
调试能力
调试能力某种程度上比编码能力更重要。查找和解决BUG会占用程序员大量的时间。查找BUG产生的根源不是一件简单的事情,需要整体的分析和经验的沉淀,同时还需要对各种调试工具熟练应用。
不少程序员,解决完一个BUG却导致了更多的隐患,没有真正把BUG产生的原因找到,只治标不治本。
对于程序员来说,掌握在合理的步骤内修复BUG,以极简的方式编写较少BUG的代码的能力,就能显著提升效率。
另外在团队中担任骨干的往往都是调试能力极强的程序员,在其他成员遇到困境之时,快速定位解决问题。
能否运用调试技能快速解决问题,是衡量一个程序员水平高低的重要标准。
— 3 —
追求简约
代码的注释是否恰到好处、函数模块和类的结构是否能让其他人直接秒懂、架构的设计是否足够清晰等等,都属于程序员追求简约的范畴。
有一种炫技程序员或者架构师,喜欢简单事情往复杂了做。明明几个类能搞定的,弄出很多中间类,明明三层架构就解决的问题,生生弄出五层。
简约是成败之间最为明显的分界点,事实上能做到简约的人,恰恰是深度理解了系统的复杂性。就好比微信是一个极度简约的产品,能做到这么简约恰恰是因为张小龙深度理解了通信和社交产品的复杂度。
一个产品功能,有人用了500行实现,你写了几千行。多出来的代码有价值吗?不仅没有价值,还会对未来接手代码的人有很大的困扰。less is more,简单就是美,这话说的真没错。
看看Google、Facebook等公司的源码,找不到太多多余的代码和结构。无论是代码层面、类层面还是架构层面,都做到了恰如其分、恰到好处。
不要多写一行无用的代码!
— 4 —
准确预测技术工期
老板想了个idea授意产品经理估工期。产品经理原型都没画出来,只有个大概想法,就找技术排工期。
这个时候,技术的内心大概多了几道菜式:清蒸产品经理、红烧产品总监、油炸CTO。
其实准确预测技术工期是程序员一项非常重要的能力。为什么这么说?只有具备这项能力,才能让开发工作游刃有余、可进可退。
事实上锻炼这种能力也并不困难,拿移动端开发来说,一个idea大概对应多少个页面多少个逻辑类,是能够估算出来的,以此为基础完全可以估出大概时间。更不用说产品文档出来之后的预测,会更为精准。
那么预测技术工期的意义在哪呢?
首先在没有出文档之前的估计,可以作为给老板的重要判断武器。做任何功能一定会投入研发力量,而往往研发力量是最宝贵的,如果在idea出来之后就能大概知道工期,对于做什么不做什么的判断,意义重大。
产品文档出来之后的精确工期呢?对控制风险和进度把控非常有帮助,这个时候的精确排期其实对风险点的估计、资源协调的能力都有很高要求。准确预测的过程其实就是风险预判的过程。
— 5 —
理解底层系统原理
处理复杂任务或解决复杂BUG时,具备深厚的底层系统知识非常重要。比如数据结构、网络协议、操作系统相关知识,等等。程序的很多问题都是源于对计算机工作原理的误解,即使是使用高级语言开发的程序也一样。另外,一些更偏应用层的架构或框架,基础一定是更底层的系统。
了解了底层原理,我们才能看穿眼花缭乱的技术背后的东西,不被层出不穷的新技术所累。
比如Docker技术兴起,改变了CI/CD的方式,推动了云原生技术的发展。那么Docker到底是什么东西呢,其底层无外乎:CGroups进行资源限制、Namespace对进程视图修改、rootfs为容器进程提供隔离后执行环境的文件系统。
了解了Docker的底层原理,才能在实际工作中更好的驾驭Docker。
再举个应用场景的例子:一提到分布式锁问题,大多数同学想到的方案是基于Redis的Master-Slave模式来实现。这个实现方案行不行?分布式锁本质是一个CP需求,基于Redis的实现是一个AP需求,乍一看基于Redis的实现是无法满足的。
脱离业务场景来谈架构都是耍流氓。从技术战略的需求层面来看,如果分布式锁在极端情况下获取锁的不一致,社交业务场景能够接受,那么基于Redis的实现是完全可行的。
如果业务是交易场景,分布式锁在极端情况下获取锁的不一致性无法接受,那么基于Redis的实现方案是不可行的。在锁强一致性的场景下,需要采取基于CP模型的etcd等方案来实现。
做出以上判断,需要深度理解底层系统原理。缺乏了这种理解,无法做出正确的架构抉择,也自然会对工作造成不利影响。
— 6 —
严格把控关键设计
无论是大的系统还是小的模块,一定都有最关键的功能。要在最关键功能上投入大量设计时间,才能规避开发过程中的各种坑。
程序员非常不情愿看到的一种情况是,需要在一些无关紧要的功能上浪费大量的时间,但你又不得不去将这个无关紧要的功能实现,因为它牵扯着这个项目的主要功能。
这种时候,就需要反思,在顶层设计的时候是否考虑周全。详细而缜密的顶层设计能够减少上述情况的发生,降低模块间的耦合性。
必须意识到每一个细小的模块都有可能成为项目的瓶颈。对于项目而言,最终的目标是合理的时间做最大的产出,实施重点就应该放在项目最主要的模块上。
拿设计IM功能来说,一个IM系统最重要的核心模块,一定是通信部分。将通信部分的各种设计搞定,其他锦上添花的方面都可以后续慢慢补充,例如客户端交互、好友关系等等。
— 7 —
拒绝完美主义
完美主义包含两种情况,一种是追求极致性能的工程师文化、还有一种是个人性格使然。无论哪一种,过分追求完美都会对业务交付产生影响。
完美主义会影响程序员的心态,过于担心外部评价或过于追求内心的安全,反而会导致设计上的过度和偏差。
程序员真正产生价值一定需要和业务结合,业务交付的及时性、健壮性、简洁性、可持续性一定是首先需要考量的事情。一定不能出现偏袒设计而牺牲生产力的情况。
不少创业公司上来就谈中台战略,并花大量研发力量去实践,最终中台没做好基础的业务保障也出问题了。在我看来,这也是追求完美主义的一种体现,诚然有一个类似阿里那样的能给各业务线赋能的中台是一个美好的愿望,但很多时候连业务方向都要多变,追求这种赋能无异于空中楼阁。
前几天我的读者群又有创业者在谈AI中台,我只想说既然是创业,咱能不能先MVP?等业务用户量更大了,再来追求更漂亮的实现?
最后的话
以上关于优秀程序员的7个能力,就说完了。其实还有一些通用的能力,比如高效学习能力、耐力、注意力等等,这些也是拉开程序员之间差距的重要因素。
今天还有个感悟:世界上的事情分两种,一种是有边界确定性强的事情:比如运动就会瘦、早起早睡会更健康、勤奋努力会具备架构思维。
另一种是无边界不确定的事情:比如练就6块腹肌、长寿100岁、成为首席架构师。如果我们连有边界确定性强的事情都搞不定还懊悔,那不要懊悔了,是因为我们压根没有真正渴望。
2020年,希望我身边的每个有足够渴望的程序员都能成为优秀的程序员。