一个人的思想和他的行为,取决于他过去十几年或者几十年的经历,自我的不断思考和日常的行为习惯。而不会因为某一天遇到的事,或者某一时刻看到某本书上的某句话,就大改变。虽然有顿悟的可能性,但我觉得那是小概率事件。
以我的总结,我们做事的方式,可以分为以下三类:
第一类,不合格的做法,缺乏努力,过于依赖他人,而且容易产生负面情绪,怨天尤人。
第二类,合格的做法,做好自己的本职工作,不给别人添麻烦,能实现自给自足。
第三类,推荐的做法,在出色完成自己本分的职责外,出于善心和利他主义帮助别人,努力做一些对社会有贡献的事情。
这么多年来,我都一直喜欢帮助别人,努力完成自己的本职工作,并尽可能地做一些对社会有意义的事件。如果哪天我们成为了明星员工,不是因为反过来要求我们做的事情都做到了,而是因为我们怀揣的价值观,付出的努力,以及对他人的帮助得到了肯定和赞许才被公司授予如此的荣誉。
此外,很重要的一点,我们不能为了追求明星级员工而去努力得到明星级员工,就像不能为了赚更多的钱而去努力付出。打个比方,在曾经高三备战高考时,我就明白一个道理,我们不能为了考高分而一味单纯地去应试,而是应该怀着一颗在未来有能力完成更大挑战且备具意义的事业去汲取知识。一旦我们所需要的知识都能充分应用自如时,任何考试,包括高考,都不过是对我们所学到的知识的一次简单的测验而已。即便高考的结果不是我们理想中的那般,但也不阻碍我们追求更崇高事业的脚步。难道说,高考失意的人就是失败的人吗?同样道理,我们更应关注在这个过程中我们做了什么,以及在内心深处我们期望追求什么。
不管怎样,以下分享内容,都是基于让我们能成为更加出色的软件开发工程师这一出发点,进而为软件行业注入更加强大的隐性推动力。至于是否成为明星级员工,则不是我们的最终目的。
遵循规则
在之前公司职时,午饭过后,我喜欢和同事在公司附近散散步。在散步过程中,我则喜欢和我的同伴分享一些我的总结、发现和思想。
其中发现的一个有趣的现象是,我发现这个社会很有意思。假设我们走进一家便利店,哪怕我们与店员素未谋面,当我们指着某瓶饮料时,店员就会拿给我们,然后结账离开。整个交易过程就完成了。但是,如果在路上,我把这瓶刚买的饮料再向另一个陌生进行兜售时,对方极其不可能买下我的饮料,他要么觉得我的饮料有问题不安全,要么觉得我是个疯子。
另一方面,在日常工作中,我们与公司内部的其他部门进行合作时,不管是私事还是公事,都能较为顺畅地进行。例如,我随时找任何一个团队提供接口文档或者一些源代码,他们都会积极地配合。但倘若我找其他公司的员工提供他们公司内部的文档或源代码时,他们不但不肯提供,很有可能在提供后我们都要被追究法律责任。
遵循规则
对于这些社会性事件的解释,我的理解是,往小的方面讲,是属于意识层面的交流。因为我们都知道对方的背景、身份,出于信任,我们会和对方进行沟通、交互。往大的方面讲,这是属于规则层面的约束和保护。在经济领域,国家赋予了个体经济和私有经济从事交易和个体经营的权利,同时也会受到监督和管理。在商业和企业中,作为员工,我们有义务履行保密协议。
不管是经济还是企业,不管是软件开发的技术领域,还是在娱乐界,都有一些约定成俗的规则。经验法则之一就是,我们需要遵循规则。明显地,在日常出行中,我们都会遵循交通规则,以确保我们自身和他人的生命及财产安全。
践行规则
将规则这一话题,折射到我们软件开发工程师身上,从小到大,又可以分为:团队约定,企业文化和行业行则。
在这一层面,我们除了要遵循规则,还要践行规则。首先,对于团队约定,如果有统一的编码规范,那么我们应该向其靠拢;如果上线前需要进行单元测试,那么也应该补充之,若有对重大项目和公司级需求的架构评审,也应该一如既往地坚持。针对这些规范、标准、安全红线等,都要理解它,实践它,坚持它。
其次,对于企业文化,则包括公司的核心价值观、公司愿景和使命等,我们也应铭记于心,并用实际行动去履行。以唯品会为例,它的价值观是:简单、创新、快速、协作。有一次,正值公司大促活动期间,在紧张地忙完一天工作下班后,我坐在陈家祠附近一家小店里吃晚饭,当时是冬季,有点冷,下着淅淅沥沥的小雨。透过朦胧的玻璃窗,我正好看到一辆有唯品会广告的公交车徐徐驶来。那一刻,我是充满骄傲的。虽然在这家小店的其他人不知道我是谁,也不知道我做了什么。但我知道,公司今晚会有一场盛大的促销活动,数以千万的消费者将会访问我参与开发的官网和活动页面,然后收到自己心仪的包裹。正是公司“成为全球一流的电子商务平台”这一愿景,以及简单、创新、快速、协作这些价值观,成为了我们几千几万名员工共同努力和奋斗的源源动力。所以,那一刻,我能为自己参与到公司如此盛大的活动,能为自己帮助了全国消费者贡献一份自己的力量而感到骄傲!
最后,则是行业规则。在软件这一行业,如果我们想更大地提升自己的技术影响力,那么更多的交流是必不可少的。在平时工作中,我们可以参与更大型系统的开发和架构设计; 在业余时间,我们可以活跃在开源社区,通过参与开源项目或者发表技术博客文章、翻译国外优秀文摘、甚至编写自己的书籍来和更多的同学进行分享和学习。这些都是可取的,也是值得去尝试和努力的。可能,很多同学对于编写文档、编写书籍、编写文字类的工作无从下手,怕写得不好。但我觉得,只要我们怀着一颗帮助他人、乐于分享的心,进而不断总结,不断提炼,慢慢地也会得到更多同行的认可与肯定。你可以把写文档当成写代码一样,谁能保证一开始写的代码就天衣无缝呢?但当你写了十万行代码时,自然就了然于心了。同样地,当你写了十万字、二十万字时,对于写作也就更加心有成竹了。多写,多练,多总结。
打破规则
有很多充满魔力的产品,都是敢于打破甚至颠覆传统商业模式的结晶。如同摄影的构图法,要想产出惊人的作品,除了要遵循规则,还要学会打破规则。
那么在软件开发这一领域,我们又该如何打破规则呢?
以开源框架为例,假设我们想开源一个自己的作品,那么我们就要首先学习已知的类似的开源项目,学习它们的思想、设计、作者当初投身其中的初衷是什么以及它希望解决的问题又是什么。当我们明白这些以后,就能针对传统做法上的不足加以改进,或者推陈出新。
另一方面,也是更为重要的,在任职过程中,我们也要注意观察、留意日常工作中,自己、身边同事和其他部门正在面临的痛点和问题,并有针对性地提出自己的解决方案。千万不要被同化其中,一直忍受明显不合理的做法。如果我们能够做得更好,为什么不去尝试呢?其中一个途径就是通过微创新,把自己的大胆尝试推广出去。此外,也可以在平时工作过程中,多与身边的同事分享自己的想法。
制定规则
最后,当我们已经遵循规则、践行规则、打破规则后,很可能我们就已经成为了某一领域的权威人士或专家。当时机合适时,我们就要参与制定新的规则。例如开发流程、上线流程、项目标准、晋升标准等。
我曾经有幸负责负责统筹团队内部的质量提升项目,并有机会与成立的虚拟小组共同制定一些开发流程与交付标准。我当时把此项目称为:约定编程。针对约定编程这一质量提升项目,我们共同制定了8个主题,分别是:最佳实践、设计文档、code review、提交测试、回归测试、发布支持、代码合并与持续集成。
约定编程的8个主题
约定编程主要介绍的是一种可以提高开发效率、减少BUG数量和降低维护成本的简明开发流程,也是一次迭代开发中的主流程。主要有:针对个人的最佳开发实践,如测试驱动开发、快速反馈;协同开发的code review和设计文档的编写;以及针对团队的持续集成,如定时构建、静态代码分析等8个主题。其中,每个主题中又分为四个阶段:初始、细化、构造和移交,以进一步明确各个阶段的职责,以及主题之间的依赖性。
在这个约定编程中,简而言之:最佳实践 + 2次code review + 2次持续集成 + 需求变更管理 = 项目质量提升。
在明确了约定编程的8个主题以及主旨后,我们就开始着手制定更细致、能够吻合当前工作情况以及具有可执行性的工作流程。
约定编程的工作流程
其中,重点的流程环节主要有以下三方面。
最佳实践
坚持测试驱动开发,搭建一键测试和自动化测试体系;有利于编写高质量、容易理解的代码,且为日益复杂的系统提供360度全方位、自我验证的安全网,快速反馈。
code review
借助代码走查,有效发现代码存在的问题和风险,形成架构明显的编程风格。
持续集成
通过项目技术债务可视化,便于成员及时关注项目质量、降低维护成本、体验编程的乐趣。
在前期共同制定了这些标准规范后,我们接着就在团队内进行了宣导和普及,针对个别主题进行了专门的分享和培训,并且建立机制持续跟进提升效果。这其中,当然也离不开团队每个成员的大力支持与配合。
分享这个约定编程的相关经验,重点不在于它本身涵盖的内容,而在于给读者传递一个信息,当有一天,你有机会参与制定规则时,大概需要开展哪些工作,以便作为一个基本的成例参考。
自我驱动力
软件开发是一个需要高智力、频繁沟通和密切合作的过程,此外,还要求我们作为软件开发工程师有极强的自我驱动力。
往后的路怎么走,取决于你自己想做什么,而不是在于别人希望你做什么。最终我们成为怎样的人,更大程度取决于我们内心想成为怎样的人,而非来自外界的要求。通俗来讲,我们可以定一个伟大的目标,然后苦逼地去实现。努力了,不一定会有结果,但如果不努力,就永远不会有任何结果。
在这一漫长的(或者说愉悦的)过程中,有一项品质,我觉得是必不可少的,那就是——自我驱动力。
学习的原动力
在很早的时候,我就意识到,如果自己想在软件这一行业有所建树,就要有雄厚的知识基础做为后盾,方能走得更远更久。为此,当树立自己的目标或者职业规划后,我便马不停蹄、日以继夜汲取知识、技术、理论和思想。从新手入门、7天精通,到核心技术、底层框架,再到工程学、编程艺术和哲学,不断积累,不断领悟。
我非常庆幸自己在过去的付出和努力,因为对知识汲取得越深,我们对事情的洞见就越为深刻,能发现一些别人难以察觉的微妙关系。然而,我发现我身边的一些同事,他们则较少,甚至多年来,对于知识的学习,则停止于毕业的那一年。倘若没有再学习新的知识,一旦我们所掌握的技能都全部派上用场后,我们就会觉得在工作上要么发挥乏力,要么会感到迷茫。这是对现状的解释,更糟糕的是,从更长远上看,将会严重制约我们职业生涯的发展。纵使我们可以保证当下不会被技术浪潮所淘汰,但如若停步不前,不学习新的东西,我们难以保证再过三年或五年,自己还能资本去谋求挑战更大、更心怡的职位和工作。
活到老,学到老。这道理大家都知道,那应该如何去学呢?
关于学习这一方法,因人而异。好比如在高三备战时,每个同学学习的方法和技巧都不一样。有些人喜欢早上5点多起床,疯狂背英语单词; 有些则喜欢在深夜专研数学题库。但在这里,可以分享下我的学习经验,以供大家参考。
有人曾说过,每个人,每天都有三个8小时,8小时睡觉,8小时上班,这些都是一样的。但真正深层次决定我们人生的是最后那8小时,即业余时间的8小时。因此,学习的第一要义,就是要充分利用业余的8小时,持续学习。我们可以在坐地铁上班过程中看下技术类的书籍,在坐公交下班的路上用手机浏览下最新的技术博客和前沿动态; 我们可以在周末的时候静下心来认真从头到尾阅读某一开源框架的开发文档,哪怕它是全英文版的,又或者亲临现场参与技术活动、分享大会等。
稍微啰嗦一下,我不建议在睡觉那8小时和上班那8小时进行学习。保持正常的睡眠是很有必要的,不管是对于个人健康还是对于学习效率。而在公司上班时学习,则要视出发点性质而定,如果是出于工作需要而查阅资料是完全符合道义的。但如果是因为暂时工作饱和度不高而去学习一些更多的知识作为备用,则建议在下班后再开始。
接下来,有一个学习的技巧,我认为很值得分享下。在业余那8小时学习,是非常困难的,因为干扰多,诱惑也多。更不用说,要在这充满短视频、朋友圈、世界杯赛事等刺激好玩的8小时内静下心来看枯燥无比的书籍,则难上加难了。那有没有好的办法呢?幸运的是,确实有一个。人在同一时间内,同时关注的事情不能超过7件事情,超过7件事情就会记不住。所以,我们一般收到的验证码都是6位,而不是7位。折射到学习时面对那么多外界的诱惑怎么办?很简单,做减法。如果在晚上看书学习时,你发现自己要去冰箱拿个酸奶来喝,还要分神留意手机有没人找你,还要时不时抬头看看显示器有没新的消息或者邮件,那么此时看书的效率肯定不高,因为有太多的事导致你分神分心。怎么办?很简单,立马去冰箱把酸奶拿出来吃了,然后把手机翻过去或丢到远离你几米的沙发上,同时把显示器关掉(甚至把声音也关掉)。把这些分神的小事先做完,把外界的干扰全部切断,然后全身心投入到学习中。犹如闭关修炼一样,进入一个宁静的环境,然后轻轻翻开书籍……
现在,打开浏览器,任意搜索某一专业术语,都不乏大量优秀的学习的资料。真正缺乏的是将知识切实应用到工作中,引进到我们负责的项目中,让知识产生价值。说白了,就要学以致用。只有当掌握了知识,应用在工作中,并产生价值后,这些知识才真正属于你,而不是别人的,更不是书本上的。
学习这一过程是漫长且艰辛的。而学习的在原动力就在于极强的自我驱动力,在于我们自己要成为怎样的人,做怎样的事。只有志存高远,方能风行天下。
做一件大事情
想一想,如果在一个公司里,我们可以在年底得到卓越的绩效,连续几年晋升加薪,有机会参加总裁午餐会,有幸代表技术人员进入后端俱乐部,成为大学堂讲师之一,甚至荣获公司级年度卓越奖,我们需要做些什么事情?至少,作为开端,我们要做一件大事情。随后,则是挑战更大的责任,尽心尽责出色越期望地完成面临的各种任务、项目和挑战。
先定个大目标,然后按照逆推法,有计划地完成它。这是一个过程,切记,这是一个过程。没有捷径,没有一蹴而就的瞬变。举个比方,上线一个新系统,则要经历需求分析与设计、编程开发、测试、回归、发布等环节。同样地,做任何一件事情,特别是大事情,都要经历一个过程。
在这个过程中,我们需要和团队一起,与公司其他部门一同密切合作,在处理好个人的情绪的同时,积极与他人达成共识,共同推进,并致力于为公司解决问题,创造价值。
我发现,这么多年来,如果我一心想着去做某件事情,最后成功的概率都会非常高,往往都能得以实现。例如花接近一年的时间考个驾照。曾经有同事赞许我说,“很佩服你,因为你做事很有规划,一旦定好目标,就能尽努力去实现和完成”。对此,我的经验就是:尽早规划,尽早行动。
如果想让自己的开源框架名列前茅需要三年时间,那么今天开始着手,那么三年后我们就能看到成果。如果明年再开始,就要四年后。这都需要时间。与此同时,作为一个成功的开源框架,稍微参考下前辈的做法,不难发现,需要完整的开发文档、活跃的交流社区、持续的更新与维护,那么我们就应该有计划地、分阶段地完成这些事情。由点到线,再由线到面,最后慢慢地就能形成气候。大事成矣。
回到工作中,如果想晋升成为资深的开发工程师,需要具备独挡一面的能力,有扎实的架构功底,曾负责过某一重要级项目的统筹工作,那么我们就应该在平时留意在这些方面不断提升,不断努力。
这一过程,特别是在实际的工作中,更显得漫长和艰辛。它要求我们,不止一天尽最大努力去完成面对的事务,还要求我们持续不断地付出和努力。如果没有强大的自我驱动力,不是我要做,而是要我做的话,恐怕自己和别人都会觉得很累。
如果真的是这样,不妨停下来问下自己的内心深处,自己到底想做什么,我的追求是什么?一旦确定后,相信你也能找到约束自己的自我驱动力。
说到自我驱动力,有一件秩事。在我面试过的那么多人中,有一位应聘者让我印象非常深刻。虽然他是刚毕业不久的应届生,但在大学四年的时间里,他考过了英语六级,拿到了驾驶证,在业余时间参加了很多项目的开发,获得多次国家奖学金,在毕业时还荣获优秀毕业生。他之所以能在大学短短四年时间里,硕果累累,肯定有很多决定性的因素,但我相信他内心深处肯定拥有着极强的自我驱动力。如今,他是我们团队中的一员,并且表现非常出色,我相信他在未来也会大放光芒。
成为一名出色的开发工程师
细致地完成需求
以做需求为例,按时按量完成并顺利上线,这是最基本的要求,能在错综复杂的情况下,在兼顾多个项目,多条业务级,各种杂事状态下依然能保证进度,甚至提前竣工,这是更优秀的表现,但还不足矣。我们还应能发现,识别存在的隐性规则,或前后不一致有予盾的产品方案,或是容易引起客诉的体验,交互或流程,并把这些一一梳理出来反馈给产品人员,项目经理,和团队。
一定要再想多几步。还要想到功能上线之初,是否要做哪些准备,有哪些checklist 清单要待办。新旧功能,新旧接口,新旧系统,切换的比例,计划和应急预案是怎样的?这些都要一并考虑。
但请记得,需求上线仅仅只是一个开始,而不是就此完成,万事大吉,反而是好戏登场的开始。
再想多一步
从上线这一刻开始,我们要考虑的东西更多,要做的事情也会更多。
当用户在使用网站、系统或者产品过程中,有任何疑问、咨询或投诉时,我们该如何快速查看日志,核对数据,然后给出准确的回复,这是一个需要思考的点。对于公司的内容运营和编辑同学,当她们修改了信息,更新了标题或文案后,需要我们协助时,又该如何做到在应对高并发的同时快速刷新缓存,刷新最新数据?与此同时,对于日常运营最为关心的事情,例如查看当前还要多久才能更新运营人员刚刚修改的标题,我们作为技术人员,能否主动进行一些微创新,为她们提供一些友好的、实用的、可视化小工具呢?另外一个非常重要的方面,一旦线上发生了故障,不管是自身内部原因,还是第三方系统外部原因,还是因为数据信息录入错误,抑或是百年一遇的断网断电等不可搞的自然界因素,这时,我们又该如何,或者凭什么,能快速定位故障的原因和问题所在?我们这时的应急方案和降级预定又是怎样?
这些,都要通盘考虑,并且提前做好准备,把事情做在前面。如果缺少对必要关键的信息纪录,那么我们将可能失去一位潜在的客户。如果缺少对运营的支持和帮助,那么她们将会缺乏对信息的掌控能力,作为技术人员,要意识到,一个网站系统,它之所以流行、受欢迎、有存在的价值,不是因为我们的代码写得有多极客,而是因为它提供了重要的信息,时刻呈现着动人的内容,或能与线下实体或服务形成闭环。
如果缺少对故障和风险的把控,我们研发和发布的系统无疑是脆弱的,弱不禁风的,支撑不了业务发展的系统,明显可预知的结果是,要么被淘汰,要么被替换。慎终思远。
总结经验,传递思想
做到这些就足矣了吗?未也。这还只是一个趋于完善的状态,但我们能做的和要做的还有很多。
关于项目质量,其实更好的建议是采用测试驱动开发。如果在大学我们一开始灌输的测试先行的思想,那么估计现在软件行业开发是另一番光景。如果前期在忙于实现功能需求而没有编写单元测试的话,可以在平时相对没那么繁忙的时候,利用碎片时间补充一下单元测试,而不是在用手机看一些八卦信息,顺便有意识地进行小步重构。觉得哪里之前做得不好的,或者是临时的解决方案,通过在单元测试的全方位保护网下,根据重构的技巧,有条不紊地推进。从点点滴滴的重构,慢慢会在我们的眼前,在我们的脑里浮现出当前领域的本质和模型,直到有一天我们突然拍着桌子兴奋地喊道,“哈!就应该这么做!”,这时你就能领悟到浮现式设计的精髓了。
以此为台阶,再往前迈一步,我们可以在不断的重构、迭代和优化过程中,对系统进行演进式设计,渐变优于剧变,如同一棵参天大树,它的成长在于每一分,每一秒,在于对每一缕阳光的吸引,和对每一次暴风的抵抗。通过演进后的系统,将能更好的顺应产品的快速迭代和业务的指数增长,它不仅能满足当前复杂的业务需求,还能从容应对未来各种不确定性。我们要编写的系统,要有活力,我们要编写一年内,几年内,甚至十几年内都能正常运行的系统,即便它退休了,它依然也会继续保存在“博物馆”内被人纪念,或者存活在新一代软件开发工程师的课堂上被学习、被参考、被借鉴。
然而,毕竟代码是晦涩的,它的思想、它的意图和它的设计,代码是无法自我诠释的,最终还要是回归到自然语言的表达上。因此,当以上这些业务需求和功能、非功能性特质、浮现式设计和演进式设计逐步完善时,我们还要通过文档,使用文字,恰当地把这些内容总结出来,分享给更多的人,让知识、洞见和思想能够传播得更远,在时间和空间上。
如果要概括的话,那就是,懂的要比别人多,想的要比别人多,做的比别人多。
小结
王明阳曾提出知行合一,格良知; 亚力山大说过要忠于自己,忠于事物本身;稻盛和夫老先生则一直坚持着利他主义; 老子曾曰慎思终远。古今中外,流传着很多大道理小故事,都是非常值得我们去学习和践行的。思想无国界,更超出了时空的限制。这些思想,对于软件工程师的人生指引,依然也蕴藏着丰富的宝藏等待我们去挖掘,去领悟,去践行。
有些规则,我们是要始终遵循的,不管是出于职业素养,还是法律法规层面。遵守规则,只是一个基本要求,或者说是底线。而践行规则,是我们走向卓越,成为明星员工的加速器。在这基础上,要学会在合适的时机打破规则,敢为人先,做一些别人没做过或不敢尝试的事情。软件开发本来就是一件充满创造性的事情,不是吗?最后,如果有机会,我们就能承担起制定规则的重任,将自己的经验、总结和成功的方式与更多的人分享,从而帮助更多的技术同学。
还记得你自己当年初学编程时深夜调试代码到凌晨的场景吗?是什么让你那么坚持,纵使是寒冬深夜舍友都酣睡时你依然能孜孜不倦地修改代码、编译代码、调试代码?是舍友要求的吗,是老师强迫的吗?都不是,而是在于你自己的自我驱动力。我希望事隔多年后,我们依然能始终保持当初那份对技术的热枕,对真理的坚持,和对自己内心深处的梦想。