这应该是最后一篇工作总结。想到今后每年可能还要再写一篇总结就有点紧张。今年的工作学习不能偷懒。
我还不敢自称“高效的工程师”,本文是最近看完的一本《The Effective Engineer》的总结和我的一些思考。写在跨年之前,也算是给自己的激励。搜了一下目前貌似尚没有翻译版,只在美帝有英文版:
https://www.amazon.com/Effective-Engineer-Engineering-Disproportionate-Meaningful/dp/0996128107/
本书还有自己的官网,包括相关的课程和材料之类:
http://www.effectiveengineer.com/
前段时间有朋友问我“什么才算是程序员大牛”,我当时的理解很简单,基本上回答是:
- 基本功扎实;
- 经验丰富,善于总结;
- 考虑更加全面,代码会考虑到所有边界情况,性能更高更加安全;
- 对软件框架和结构的设计更加简洁清晰,虽然这不意味着简单;
- 会更加愿意涉猎和学习,并且爱总结分享;
- 有更强的查错能力;
翻完这本书之后对此有了一些新的认识。一个优秀的程序员不仅有过硬的技术功力,还应该在工作上拥有正确的态度和方法,如对自身时间的管理,与队伍的交流,等等软技能。这本书可以把它看成为成长为优秀工程师的参考。
作者 Edmund Lau 曾在谷歌这样的大公司任职,也参与过小的创业公司如 Ooyala,Quora 和 Quip 等。他认为所谓“高效的工程师”,就是能在投入同样的时间下,获得更有价值的输出,能够完成更具有影响力的任务,从而为公司和自己创造更大的价值。这是个简单的公式:
效率(Leverage) = 产出的影响 / 投资的时间
而作为高效的工程师,就是要努力提高这个“效率”。书里介绍了几种实现“高效”的方法,基本上都是在讨论工程师的“思路”和“心态”等软技巧。以下是我对整本书的总结。
一,树立正确的认识
着重在高效的事情上
这是一个非常显而易见的道理,但是反思后我觉得我并不是所有时候都会考虑到这一点。所谓高效并不是简单地投入更多的时间,而是通过学习,提升,总结经验,找到高效的方法,才是真正提高“效率”的方法。这是一个工程师应该一直保持的心态。
优化自己的学习
你的工作应该给你带来增长:代码技术,个人能力等等个人实力的增长。如果你反思发现你现在的工作或业余时间里并没有给你带来这样的机会,应该及时作出改变。比如找到更加适合学习的任务,更加具有挑战性的任务,学会和公司里的工程师交流,留出自己的时间自学等等。
优先重要的任务
学会了解什么任务是当前最紧急的最重要的,能使得你投资的时间带来最高的效用。不同的项目,在不同的时段,也会有不同的评估效用的方法,所以这是一个经常需要重新思考的问题。经常问自己:“这是我现在能做的最重要的任务吗?”
作者对日常任务作出了一个划分,基本上可以分为:
- 重要且紧急的任务,如 Deadline,Bug,等等;
- 重要但并不紧急的任务,如工作计划,定期学习,等等;
- 并不重要但紧急的任务,如开会,电话,来自外界的干扰等等;
- 不重要也不紧急,比如,嗯,刷脸书?
第一类任务永远应该放在最先着手,具有最高的优先权;而第二类较为常规例行的任务,需要定时留出适当的时间。而后两类任务,应该尽量避免。
二,执行力
执行力说的是有效执行完成实际工作的能力。作者提出了一些相对较为普适的观点和做法,在不同的软件工程方向都具有很强参考价值的做法。
投资在改进迭代速度上
软件的迭代速度指的是,“开发 -> 编译或构建 -> 测试 -> 调试”这一整个周期迭代的速度。改进迭代速度的方式有很多,如尽量使用小的改动并及时测试以发现问题,合理利用工具加快开发速度,投资在自动化上避免重复的工作,等等。
作者提到了几个例子,比如,优化配置你的工作环境。合理地配置你的工作环境可以大幅度地减少重复的工作,提升你的工作效率,一个好的编程环境加工具甚至能够及时帮助你发现问题(比如自动语法检测)。不同的语言环境有不同的工具,投资在这上面学习的时间通常都是值得的。
另一个例子是持续集成。持续集成指每次更新代码,都通过工具或自动化脚本在新的代码上运行测试以保证新代码的质量,使得作者能够在最快时间内获得问题的反馈并定位问题。一个团队在这上面的一定要有投资。著名的工具有 Jenkins
等。
还有一个例子是,学习一门高级语言或是脚本语言,可以在很多时候作为创建原型的工具。这样可以快速实现并验证自己的想法。
测量你想要改进的指标
一个软件工程项目都应该有评估其表现的一系列指标,比如网站有不同页面的访问量,用户转化率,底层性能软件有不同模块所耗时间,等等。测量指标的选取,以及测量上的精确程度,都会影响迭代和反馈的速度和质量。
比如作者提到,谷歌在早期为了提升用户搜索的质量,希望通过指标来衡量用户对搜索的满意程度。他们采取过很多指标,但最终工程师们采用的最满意的指标是:“长点击(long click)”,意味着用户点击一个结果后,很长一段时间都不返回到搜索页面上。“长点击”意味着谷歌返回了令用户真正满意的搜索结果。这个指标的选取对谷歌对结果的优化带来了重要的影响。
合理的指标起到了指明方向的作用。一个软件工程没有合理的指标,团队就会像在黑暗中摸索。
及时验证你的想法
软件工程上及时快速地验证你的想法,比埋头不停地生产代码要有效得多,也能为你规避更多的风险。很多团队话费大量时间制造“秘密项目”,而始终得不到反馈,最终结果往往是得不到好评,而且浪费了大量的时间。
验证想法的方式有很多种,比如通过测试验证你的正确性,及时与团队讨论验证你的思路,及时发布更新从用户身上获取反馈。单独长时间没有得到反馈的工作,往往会走进死胡同。
提高项目估算技能
一个优秀的工程师应该对项目的所需要的时间有正确的评估。这是一个听上去很简单但是实际上非常难的技能。项目中可能出现各种开始被忽视的问题,都会非常可能拖延项目的时间。没有正确的项目时间估算,可能会导致项目的拖延,对团队合作出现影响,甚至影响到整个公司。
作者对项目时间管理的经验和建议:
- 团队交流合作所消耗的时间往往比你想象得多。增加人手也会增加交流合作的费时,这一点往往会耗费更多的时间。时间估计并不能简单地通过人×月对工作量进行估算(有本《人月神话》专门讨论了这个问题);
- 将任务分解成精细化的任务;
- 让实际参与任务的工程师决定时间;
- 根据实际情况进行估计,考虑以往的时间分布作出判断,而不是使用理想的时间;
- 为未知因素流出足够的时间。
三,创造长期的价值
以实用主义平衡软件质量
软件的代码质量和可读性对软件长期的维护起到了重要的作用,为了提高软件的质量,一个队伍需要有合理的代码审查机制,通过自动脚本和团队之间的互相审查保证提交的代码质量;还有如之前提到的自动化的测试,保证每一次的提交都能通过测试。
另一点是及时偿还“技术债”。“技术债”指的是解决问题而临时实现的“快而脏”的解决方案 ,虽然能够在短时间内对软件进行“修补”,但是长期大量的“技术债”会对软件质量造成影响,使得软件的结构越来越“脏”,增加维护上的难度和出错的风险。
另外作者提到一点,在大型复杂的软件中,应该通过抽象的表达来构建软件。正确的抽象表达会使得软件结构清晰易懂,使得在抽象层之上的新功能的开发更加简单直接,也使得整个软件项目更加容易维护,取得更高的软件质量。
Pick the right ones, and programming will flow naturally from design; modules will have small and simple interfaces; and new functionality will more likely fit in without extensive reorganization.
文中举了一个令我印象很深的例子:MapReduce. MapReduce 是最先由谷歌提出并在内部实现,将大规模集群的数据处理接口抽象为 Map(映射),和 Reduce(归纳),并将底层复杂的操作完全对程序员透明,使得大规模数据算法开放大大简化。
可以说,软件工程中的最难点,但也是最有意义的一点就是找到合理的抽象。
减少运作的耗费时间
Instagram 在 2012 收购前拥有员工 13 人,但是坐拥了 4000 万左右的用户。能够做到这一点和团队的高效性是分不开的。
作者提到几点减少运作成本的建议:
- 尽量使用经过时间检验的工具,而不是一味追求新的技术;
- 尽量简化系统的复杂性;
- 第一次设计往往会很复杂,学会不断简化整个系统的架构;
- 在增加系统功能的时候始终考虑未来的运行和维护的成本。
作者的另一个建议是,在系统出错时,应该选择让系统快速报错。虽然这并不意味着让用户直接看到错误,但是需要直接反映出来使得程序员能够快速得到问题的反馈。没有及时反馈的错误就会像定时炸弹一样埋在软件里。
自动化
把所有需要重复,可以自动化的部分都进行自动化,以减少运行的成本。如上文所说的测试自动化,团队工作中有很多任务都可能需要自动化。在自动化上投资的时间往往都会在长远上得到回报。
投资整个团队的建设
这是作者对整个团队建设提出的意见,包括如何通过面试扩张团队,影响整个团队的工作效率,促进整个团队甚至公司的进步等。
- 让团队里所有人参与到新员工雇佣的决策当中;
- 投资在员工的新上任过程,比如熟悉所需的技能,熟悉现有的代码,通过导师制度让新员工逐渐适应工作,培训,等等。这一点对新员工的工作效率提升非常重要;
- 你的职业生涯取决于你队伍的成功与否;
- 分享代码权:让团队中所有人有机会接触甚至了解代码。不仅可以加强队伍对整个项目的理解,互相提供建议,也可使得团队在缺少人的情况下仍能正常运作;
- 分析以往的错误,让整个团队从错误中汲取教训。