Skip to main content

写给工程师的 10 条精进原则

引言

时间回到8年前,我人生中的第一份实习工作,是在某互联网公司的无线搜索部做一个C++工程师。当时的我可谓意气风发,想要大干一场,结果第一次上线就写了人生中第一个Casestudy。由于对部署环境的不了解,把SVN库里的配置文件错误地发到线上,并且上完线就去吃晚饭了,等吃饭回来发现师傅在焦头烂额地回滚配置。那次故障造成了一个核心服务20分钟不可用,影响了几百万的用户。

这仅仅是一个开始,在后来半年的时间里,我几乎把所有职场新人可能犯的错误都犯了个遍。架构师让我调研一个抓取性能提升方案,我闷头搞了两周,也没有得出任何结论;本来安排好的开发计划,由于我临时要回去写论文,搞得经理措手不及;参加项目座谈会,全程“打酱油”……那段时间,自己也很苦恼,几乎每天晚上11点多才走,很累很辛苦,但依然拿不到想要的结果。
8年过去了,自己从一个职场小白逐步成长为一名技术Leader。我发现团队中的很多同学在不停地重复犯着自己当年类似的错误。他们并不是不努力,到底是哪里出了问题?经过一段时间的观察与思考后,我想我找到了答案。那就是:我们大多数同学在工作中缺乏原则的指导。原则,犹如指引行动的“灯塔”,它连接着我们的价值观与行动。不久前,桥水基金创始人雷·达里奥在《原则》一书中所传达的理念,引爆了朋友圈。每个人都应该有自己的原则,当我们需要作出选择时,一定要坚持以原则为中心。但是在现实生活中,我们往往缺少对原则的总结,对于很多人来说这是一门“只可意会不可言传”的玄学,是属于老司机的秘密,其实不然。
“追求卓越”是美团的价值观。作为一名技术人员,我们应该如何践行呢?本文总结了十条精进原则,希望能够给大家带来一些启发,更好地指导我们的行动。

原则一:Owner意识

“Owner意识”主要体现在两个层面:一是认真负责的态度,二是积极主动的精神。
认真负责是工作的底线。首先,要对我们交付的结果负责。项目中每一个设计文档、每一行代码都需要认真完成,要对它的质量负责。如果设计文档逻辑混乱,代码没有注释,测试时发现一堆Bug,影响的不仅仅是RD的工程交付质量,还会对协同工作的RD、QA、PM等产生不好的影响。久而久之,团队的整体交付质量、工作效率也会逐步下降,甚至会导致团队成员之间产生不信任感。其次,我们要对开发的系统负责。系统的架构是否需要改进,接口文档是否完善,日志是否完整,数据库是否需要扩容,缓存空间够不够等等,这些都是需要落地的事情。作为系统Owner,请一定要认真履行。
积极主动是“Owner意识”更高一级的要求。RD每天要面对大量的工作,而且很多并不在计划内,这就需要具备一种积极主动的精神。例如我们每天可能会面对大量的技术咨询,如果客户提出的问题很长时间得不到回应的话,就会带来不好的客户体验。很多同学说忙于自己的工作没有时间处理,有同学觉得这件事不是很重要,也有很多同学是看到了,但是不知道怎么回答,更有甚者,看到了干脆装没看见。这些都是缺乏Owner意识的体现。正确的做法是积极主动地推动问题的解决,如果时间无法排开或者不知道如何解决,可以直接将问题反馈给能解决的同学。
积极主动还可以表现在更多方面。比如很多同学会自发地梳理负责服务的现状,根据接口在性能方面暴露的问题提出改进意见并持续推动解决;也有同学在跨团队沟通中主动承担起主R的角色,积极发现问题、暴露问题,推动合作团队的进度,保证项目顺利推进。这些同学无一不是团队的中坚力量。所以,我们在做好自己份内工作的同时,也应该积极主动地投入到“份外”的工作中去。一分耕耘一分收获,不要给自己设限,努力成为一个更加优秀的人。

原则二:时间观念

相信大家都有时间观念,但是真正能执行到位的可能并没有那么多。互联网是一个快速发展的行业,RD的研发效率是一个公司硬实力的重要体现。项目的按期交付是一项很重要的执行能力,在很大程度上决定着领导和同事对自己靠谱程度的评价。大家可能会问:难度几乎相同的项目,为什么有的同学经常Delay,而有的同学每次都能按时上线?一个很重要的原因,就是这些按时交付的同学往往具备如下两个特质:做事有计划,工作分主次。
工作安排要有计划性。通常,RD在设计评审之后就能预估出精确的开发时间,进而再合理地安排开发、联调、测试计划。如果是项目负责人,那么就会涉及协调FE、QA、PM等多个工种的同学共同完成工作。凡事预则立,不预则废。在计划制定过程中,要尽可能把每一项拆细一点(至少到pd粒度)。事实证明,粒度越细,计划就越精准,实际开发时间与计划之间的误差就会越小。
此外,务必要规定明确的可检查的产出,并在计划中设置一些关键的时间点进行核对。无数血淋淋的事实告诉我们,很多项目延期都是因为在一些关键交付点上双方存在分歧造成的。例如后台RD的接口文档计划在周五提供,FE认为是周五上午,而RD认为是周五下班前提交,无形中会给排期带来了1pd的误差。所以,我们要做到计划粒度足够细,关键时间点要可检查。
工作安排要分清楚主次。我们每天要面对很多的事情,要学会分辨这些工作的主次。可以尝试使用“艾森豪威尔法则”(四象限法则),把工作按照重要、紧急程度分成四象限。优先做重要紧急的事情;重要不紧急的事情可以暂缓做,但是要持续推进;紧急不重要的事情可以酌情委托给最合适的人做;不重要不紧急的事情可以考虑不做。很多项目无法按期交付的原因,都是因为执行人分不清主次。比如在开发中需要使用到ES,一些不熟悉ES的同学可能想系统性地学习一下这方面的知识,就会一头扎进ES的汪洋中。最后才发现,原本一天就能完成的工作被严重拖后。实际工作中,我们应当避免这种“本末倒置”的工作方式。在本例中,“系统性地学习ES”是一件重要但不紧急的事情。要学会分辨出这些干扰的工作项,保证重要紧急的事情能够按时交付。

原则三:以终为始

“以终为始”(Begin With The End In Mind),是史蒂芬·柯维在《高效能人士的七个习惯》中提到的一个习惯。它是以所有事物都经过两次创造的原则(第一次为心智上的创造,第二次为实际的创造)为基础的。直观的表达就是:先想清楚目标,然后努力实现。
在工作中,很多RD往往只是埋头走路,很少抬头看天。每次季度总结的时候,罗列了很多项目,付出很多努力。但是具体这些项目取得了哪些收益,对业务有哪些提升,却很难说出来。这就说明在工作中并没有遵守“以终为始”这一原则。此外,很多同学在做需求的过程中,对于目标与收益关注不够,系统上线之后,也没有持续地跟进使用效果。这一点在技术优化项目中体现的尤为明显。
例如在一个接口性能优化的项目中,经过RD的努力优化,系统TP99缩短了60%,支持QPS提升了2倍。但是系统到底需要优化到什么程度呢?是不是缩短60%,提升2倍就能满足需求呢?在优化之前,很多同学常常忘记设置一个预设的目标(TP99小于多少,支持QPS大于多少)。我们必须清楚,优化一定是有原因的,比如预期某节假日流量会暴增或者某接口超时比例过高,如果不进行优化,系统可能会存在宕机风险。解决特定的问题才是技术优化的最终目的,所以要根据问题设定目标,再进行优化
“以终为始”,这一原则还可以作用于我们的学习中。很多同学看过很多技术文章,但是总是感觉自己依然一无所知。很重要的一个原因,就是没有带着目标去学习。在这个信息爆炸的时代,如果只是碎片化地接收各个公众号推送的文章,效果几乎可以忽略不计。在学习之前,我们一定要问自己,这次学习的目标是什么?是想把Redis的持久化原理搞清楚,还是把Redis的主从同步机制弄明白,亦或是想学习整个Redis Cluster的架构体系。如果我们能够带着问题与目标,再进行相关的资料搜集与学习,就会事半功倍。这种学习模式的效果会比碎片化阅读好很多。

原则四:闭环思维

你是否遇到过这样的场景:参加了一个设计(或需求)评审,大家兴致勃勃地提了很多合理的意见,等到再次评审的时候,却发现第一次提的很多问题都没有得到改进,很多讨论过的问题需要从头再开始讨论。这种情况就是一种典型的工作不闭环。
之前看过一句话:一个人是否靠谱,就看他能否做到凡事有交代,件件有着落,事事有回音。这就是闭环思维的重要性。它强调的是一种即时反馈闭环,如果别人给我们分配了一个任务,不管完成的结果如何,一定要在规定的时间内给出明确的反馈。
例如在跨部门的沟通会议中,虽然各方达成了一致,会议发起者已经将最终的记录周知大家。但是,到这一步其实并没有完成真正的闭环,在落地执行过程中很可能还存在一些潜在的问题。例如,会议纪要是否经各方仔细核对并确认过?会议中明确的To Do进展是什么?完成结果有没有Check的机制?如果这些没有做到的话,就会陷入“沟通-发现问题-再沟通-再发现问题”的恶性循环中。
真正的闭环,要求我们对工作中的事情都能够养成良好的思维习惯,沟通要有结论,通知要有反馈,To Do要有验收。
“闭环思维”还要求能够定期主动进行阶段性的反馈。刚参加工作时,我接了一个工期为两个月的项目。整个项目需要独自完成,自己每天按照计划,有条不紊地进行开发。大概过了两周之后,Leader询问项目进度,虽然我已经跟他说没问题。然而,Leader告诉我,因为我每天对着电脑也不说话,让他心里很没底。
这时,我才意识到一个很重要的问题,我跟Leader之间存在信息不对称。从那以后,我就时不时得跟他汇报一下进度,哪怕就只有简短的一句话,也可以明显感觉,他对我的信心增加了很多。特别是我做Leader之后,对这种闭环反馈的理解,就更加深刻了。从Leader的角度看,其实只是想知道项目是否在正常推进,是否遇到问题需要他协助解决。

原则五:保持敬畏

“君子之心,常怀敬畏”,保持敬畏之心能够让我们少犯错误。在工作中存在各种各样的规范,例如代码规范、设计规范、上线规范等等。我们必须明白,这些规范的制定一定是基于某些客观原因的,它们都是历史上无数Case积累而来的经验。团队里的每一个成员都应该学习并严格遵守,这一点对于新人尤其重要。
当我们进入到一个新的团队,请先暂时忘掉之前的习惯,要尽快学习团队既有的规范,并且让自己与团队保持一致。以编码风格为例,很多同学往往习惯于自己之前的代码写作风格,在做新公司第一个项目时,也按照自己的习惯进行变量、包的命名等等。结果在代码Review过程中,被提了很多修改意见,不得不返工重写,得不偿失。如果能够保持敬畏之心,提前了解编码规范,这种问题完全可以避免。
类似的问题,还包括对上线流程的不了解,对回滚操作不熟悉,对SRE线上变更过程不了解等等。除了这些显而易见的规范,还有一些约定俗成的规则。个人建议是:如果有事情拿不准,不妨多问问其他同事,不要凭自己的感觉做事情。
保持敬畏之心并不意味着要“因循守旧”。在我们充分了解这些规范和约定之后,如果觉得存在不妥之处,可以跟全组同学讨论,是否采纳新的建议,然后及时去更新迭代。其实,让规范与约定与时俱进,也是另一种形式的敬畏。

原则六:事不过二

“事不过二”,是我们团队一贯坚持的原则,它可以解读为两层含义。
一层含义是“所有的评审与问题讨论,不要超过两次”。之所以有这样的要求,是因为我们发现,很多RD都把时间花费在一些无休止的评审与问题讨论中,真正投入到实际开发中的时间反而很少。在实际工作场景中,我们经常会遇到一些不是很成熟的需求评审。这些需求文档,要么是背景与目标含糊不清,要么是产品方案描述不够细化,或者存在歧义。RD与PM被迫反复进行讨论,我曾经遇到过一个需求评审,进行了三次还被打回。
同样的问题,在设计评审中也屡见不鲜。方案固然需要经过反复的讨论,但是如果迟迟不能达成一致,就会耗费很多RD与PM的宝贵时间,这就与提升研发效率的理念背道而驰。因此我们团队规定:所有的评审最多两次。通过这种方式,倒逼利益相关方尽可能地做好需求与方案设计。评审会议组织前,尝试与所有相关人员达成一致,询问对方的意见,并进行有针对性的讨论,这样能够大大提升评审会议的效率和质量。如果在第一次评审中不通过,那么就只有一次机会进行复审。一旦两次不通过,就需要进行Casestudy。
“事不过二”原则的另一层含义,是“同样的错误不能犯第二次”。每次故障之后,Casestudy都必须进行深刻的总结复盘,对故障原因进行5Why分析,给出明确可执行的To Do List。每次季度总结会,大家自我反省问题所在,在下个季度必须有所改善,不能再犯类似的错误。孔子云:“不迁怒,不贰过”,在错误中反思与成长,才能让我们成为更优秀的人。

原则七:设计优先

“设计优先”这条原则,相对来说更加具体一些。之所以单列一项,是因为架构设计太重要了。Uncle Bob曾说过:“软件架构的目标,是为了让构建与维护系统的所需人力资源最小化。”
架构设计,并不仅仅关系到系统的质量,还关乎团队的效能问题。很多团队也有明文规定,开发周期在3pd以上的项目必须有设计文档,开发周期在5pd以上的项目必须有设计评审。在具体的执行过程中,由于各种原因,设计往往并不能达到预期的效果。究其原因,有的是因为项目周期紧,来不及设计的足够详细;有的是因为RD主观上认为项目比较简单,设计草草了事。无数事实证明,忽略了前期设计,往往会导致后续开发周期被大幅拉长,给项目带来了很大的Delay风险。而且最可怕的是,不当的设计会给项目带来巨大的后期维护成本,我们不得不腾出时间,专门进行项目的优化与重构。因此,无论什么时候都要记住“设计优先”这一原则。磨刀不误砍柴工,前期良好的设计,会给项目开发以及后期维护带来极大的收益。
“设计优先”这一原则,要求写别人看得懂的设计。我们了解一个系统最直接的途径就是结合设计文档与代码。在实际工作中,很多同学的设计文档让大家看得一头雾水,通篇下来,看不出系统整体的设计思路。其实,设计的过程是一种智力上的创造,我们更希望它能成为个人与集体智慧的结晶。如何才能让我们的设计变得通俗易懂?我个人认为,设计应该尽量使用比较合理的逻辑,进而把设计中的一些点组织起来。比如可以使用从抽象到具体,由总到分的结构来组织材料。在设计过程中,要以需求为出发点,通过合理的抽象把问题简化,讲清楚各个模块之间的关系,再详细分述模块的实现细节。做完设计之后,可以发给比较资深的RD或者PM审阅一下,根据他们的反馈再进行完善。好的设计,一定是逻辑清晰易懂、细节落地可执行的。

原则八:P/PC平衡

“P/PC平衡”原则,即产出与产能平衡原则。伊索寓言中讲述了一个《生金蛋的鹅》的故事。产出好比“金蛋”,产能好比“会下金蛋的鹅”。“重蛋轻鹅”的人,最终可能连产蛋的资产都保不住;“重鹅轻蛋”的人,最终可能会被饿死。产出与产能必须平衡,才能达到真正的高效能。为了让大家更清晰的了解这一原则,本文举两个例子。
从系统的角度看,每一个系统都是通过持续不断地叠加功能,来实现其产出,而系统的产能是通过系统架构的可扩展性、稳定性等一系列特性来表征。为了达到产出与产能的平衡,需要在不断支持业务需求的过程中,持续进行技术架构层面的优化。如果一味地做业务需求,经过一定的时间,系统会越来越慢,最终影响业务的稳定性;反之,一个没有任何业务产出的系统,最终会消亡。
再从RD的角度来看这个问题,RD通过做需求来给公司创造价值,实现自己的产出。而RD的产能是指技术能力、软素质、身体健康状况,有这些资本后,我们才能进行持续的产出。在日常工作中,我发现很多RD往往只重视产出。他们也在很努力地做项目,但是每一个项目所使用的方法,还是沿用自己先前一贯的思路。最终,不仅项目做得一般,还会抱怨自己得不到任何成长。这就是P/PC不平衡的体现。如果能在做项目的过程中,通过学习和总结持续提升自己的技术能力和软素质,并将其应用于项目实施交付中,相信一定会取得双赢的结果。
“P/PC平衡”原则还适用于很多其他的领域,例如团队、家庭等,我本人也非常推崇这一原则。希望大家也能将其作为自身的一项基本原则,努力寻找到产出与产能的平衡点。

原则九:善于提问

“善于提问”,首先要勤于提问。求知欲源于好奇心,是人类的一种本能。在工作中要养成勤于提问的好习惯,不懂就问,不要因为自己一时懒惰或者碍于情面,就放弃提问的机会。当遇到不同的观点时,也要礼貌地问出来。波克定理告诉我们,只有在争辩中,才可能诞生最好的主意和最好的决定
在设计评审、代码评审这类体现集体智慧的活动中,遇到有问题的地方一定要提出来。我经常看到,很多同学评审全程一言不发,这就是浪费大家的时间。设计评审的目的,是让大家针对方案提出改进意见并达成一致,如果全程“打酱油”,那就失去了评审的意义。我们鼓励大家多提问,把自己内心的疑惑表达出来,然后通过交流的方式得到答案。
“善于提问”,还要懂得如何提问。为什么同样是参加设计评审,有的同学就能提出很好的问题,而有的同学却提不出任何问题?除了知识储备、专业技能、经验等方面的差异外,还有一点很重要:这就是批判性思维。
批判性思维主张通过批判性思考达到理性思维,即对事物本质的认知和掌握。关于如何进行批判性思维,大家可以参考一些经典的图书如《批判性思维》、《学会提问》等。在工作中面临一项决策时,会有各种各样的意见摆在你面前,所以我们必须要学会使用批判性思维来进行分析,每个人的论据是否可靠,论证是否合理,是否有隐含的立场。同样,在阅读一篇技术博客的时候,也要使用批判性的思维,多问几个为什么,作者得出的结论是否合理?论据是否充分?只有这样,才能不断地获取真正的知识。

原则十:空杯心态

“满招损,谦受益”,“空杯心态”是最后一项原则。我觉得这也是一个人能够持续成长的前提。做技术的人,骨子里通常有股傲气,并且会随着资历、成绩的提升而不断增加。初入职场的小白,可能会非常谦虚,但是工作几年之后,专业技能逐步提升,可能还取得了一些小成就,人就会越来越自信。这时候,如果不能始终保持“空杯心态”,这种自信就会逐步演变为自满。自满的人,往往表现为工作中把别人的建议当成是批评,不接受任何反对意见,学习上也缺乏求知的动力,总是拿自己的长处去跟别人的短处做比较。其实每个人多少都会有一些自满,可怕的是不知道甚至不愿承认自满。
保持“空杯心态”这一原则要求我们时刻进行自我检视与反省。在工作中,多去跟不同级别的同学聊一聊,或者做一个360度评估,这有助于我们更加客观地评价自己。在横向对比中,多向那些优秀的同学看齐,学习他人的优点。很多同学在设计评审或者代码Review过程中,针对别人提出的问题与建议,往往都采用一种对立的态度。错误地认为别人是在挑刺,是在针对自己。诚然,在某些方面,我们可能确实比其他人想得深入,但是这不代表在所有方面都能考虑周全。对于别人的建议,建议使用“善于提问”原则里提到的批判性思维仔细分析一下,虚心地吸取那些好的建议。
工作学习就像“练级打怪”,技能储备的越多,就越容易走到最后。保持空杯心态,可以让我们发现很多以前注意不到的新能力,我们要做的就是努力学习它,将它们转化为自己能力库的一部分。

总结

以上,是我总结的工作与学习的十条基本原则。其中有的侧重于个人做事情的方法,如“Owner意识”、“时间观念”、“以终为始”、”闭环思维”;有的侧重于团队工作标准规范,如“保持敬畏”、“事不过二”、“设计优先”;有的侧重于团队或个人效能提升,如“P/PC平衡”、“善于提问”、“空杯心态”。这些原则是我多年在工作与学习中,不断总结得来的经验。希望在大家面临选择时,这些原则能够起到一定的帮助和指导作用。
以原则为中心地工作与生活,让自己与团队变得更加强大。

作者介绍:云鹏,2014年加入美团,先后参与了美团酒店供应链体系、分布式调度系统的建设,现在负责美团旅行客户关系管理系统、基础信息服务的建设工作。

Comments

Popular posts from this blog

CKA Simulator Kubernetes 1.22

  https://killer.sh Pre Setup Once you've gained access to your terminal it might be wise to spend ~1 minute to setup your environment. You could set these: alias k = kubectl                         # will already be pre-configured export do = "--dry-run=client -o yaml"     # k get pod x $do export now = "--force --grace-period 0"   # k delete pod x $now Vim To make vim use 2 spaces for a tab edit ~/.vimrc to contain: set tabstop=2 set expandtab set shiftwidth=2 More setup suggestions are in the tips section .     Question 1 | Contexts Task weight: 1%   You have access to multiple clusters from your main terminal through kubectl contexts. Write all those context names into /opt/course/1/contexts . Next write a command to display the current context into /opt/course/1/context_default_kubectl.sh , the command should use kubectl . Finally write a second command doing the same thing into ...

OWASP Top 10 Threats and Mitigations Exam - Single Select

Last updated 4 Aug 11 Course Title: OWASP Top 10 Threats and Mitigation Exam Questions - Single Select 1) Which of the following consequences is most likely to occur due to an injection attack? Spoofing Cross-site request forgery Denial of service   Correct Insecure direct object references 2) Your application is created using a language that does not support a clear distinction between code and data. Which vulnerability is most likely to occur in your application? Injection   Correct Insecure direct object references Failure to restrict URL access Insufficient transport layer protection 3) Which of the following scenarios is most likely to cause an injection attack? Unvalidated input is embedded in an instruction stream.   Correct Unvalidated input can be distinguished from valid instructions. A Web application does not validate a client’s access to a resource. A Web action performs an operation on behalf of the user without checkin...