作为一位经验丰富的开发者,我分享20条软件工程的经验法则

发表时间: 2020-05-12 22:22

作者 | Mickey Muldoon

译者 | 孙薇

出品 | CSDN(ID:CSDNnews)

我并非一个10倍的开发者(10倍开发者指的是在其领域,所产生的成果是其他同事的十倍),从拨号时代以来,我从未建过网站,大学毕业没几年我就选择了编程,因为对于政府和政治这些东西我并不擅长,导致事业一度陷入僵局。

因此,大约5年中我一直在朝九晚五地写代码,那段时间我还养着3个孩子,刚开始编程时2个才出生,1个2岁。所以,我不是那种通宵达旦、周末无休的程序员,我还得照顾家人。

大约一年前,我开始为自己的首个开源项目投入贡献,那是我的第一个副业项目,一个会议网站。

我从未完整地读过一本软件工程相关的书籍。

总而言之,我只是一个1倍开发者,所做的事情也只够让我体面地混过去而已。

作为一个1倍开发者,我大量使用了常规知识,对于软件工程我没太多有趣的新东西可说。

总的来说,我还没抽出时间大量从事工作以外的内容,或者在副业上再多花些时间,或者真正广泛地读些东西,或者大幅超越自己。我在主业和副业上都难以抽出更多时间。

但我感觉到了自己的雄心,想要成为一个1.1倍的开发者,也在尝试找到办法来实现。

这阵子我的空闲时间多了一些,由于新冠疫情和隔离,导致我虽在休假却无处可去,孩子们也因为疫情而只能休着“春假”在家学习,于是就有了本文。

因此我打算以如下方式将我的软件工程学知识作以阐述:

1. 写下我关于某些软件工程学话题的愚见;

2. 将我的想法分享给更聪明的人,请求大家猛烈地批评指正;

3. 基于第二点更新;

4. 尝试找出方法,以查找软件工程相关的信息,或者基于新项目的反馈,并根据优先级将有用的信息排序,并与第一点相结合。

事不宜迟,以下就是我关于1倍开发者的经验法则。

规则本元

规则1:规则是个好东西

根据我的观察,人类天生就在寻求非理性、不一致性和权威主义的模式,也就是说,一般而言大多数人会不自觉倾向于将目标设定为令领导者满意的方式,复制周边人的做法,并遵循某些已有的模式。在一个复杂的世界里,保持理性和一致性非常困难。因此,直接完成“领导指派的任务”或者“同事都在做的事情”就成了简便的选择。

在许多情况下,这条策略能很好地服务于人,而且确实有助于建立“团队一致性”。但是,如果你的目标真的很外延——比“团队一致性”要求更高,涉及到完成团队外部的目标时,尝试保持理性和一致性就非常有价值了。

我认为,经验法则(或者你想换个说法,改叫原则)有助于提供一些保护、一些框架、一些支架,让人们得以摆脱默认思维模式。它们有助于增强某种程度的逻辑一致性;在存在许多相互竞争的优先事项和价值观时,有助于将重点集中在会话上;当你在无休止的选项中尝试找到决策方案时,有助于提供一种更加明确和周全的便捷方案。

我在亚马逊工作,这家公司以存在一套普适原则而闻名,这些原则在招聘时,在艰难决策时,在评估权衡时都会体现。而且我认为,这些原则的存在对亚马逊是好事,并非由于它们包含任何天才性的特殊之处,而仅仅是因为拥有这些原则总比退回到盲从领导者更好。

思考很困难,决策也很难,有周全的规则来指导决策有助于我们做得更好。

以上这些的意思是:下面列出的经验法则与亚马逊的并不完全相同,大多只是在我思考这些主题时,跳到脑海里的经验法则而已。

生产力及学习

规则2:我学到的大多东西在其情境之外都没什么用处

有时候我会听人说起,IQ测试唯一衡量的只是“你在参加IQ测试时的表现”。我认同这个说法,并同意大多数知识都是高度情境相关的。从大学开始,我从事了大约7份不同的“真正工作”,每份都有不同的职务头衔。在亚马逊,我做过两个完全不同的产品和行业。

我发现,我在一份工作中学到的大多知识(差不多90%)对下一份来说都是没用的,即便是在同一个职业领域中。倒并非完全无用——另外的10%可能是非常重要的10%,比如如何更好地处理电子邮件,或者如何应对办公室政治。但当我开始下一份工作时,我所学到的大多知识仍然全都是“一次性的”,与特定公司的运作方式相关的特定知识。

亚马逊可能是个极端案例,因为这里的开发者花了大量时间来掌握公司的内部工具和商业概念,这些在别的公司完全见不到。或许我在某种程度上也被这些感染了,我知道其他开发者有着不同的经验,他们所掌握的特定技术和技能实际上可以从一份工作迁移到下一份。

在学校时(我的确花了几年时间工作),事实上大多知识都是不可转移的。在某个领域学到的东西,对其他领域并无帮助。

因此,我任性地倾向于这样的想法:如果我今天90%的工作对于下一份工作没什么用,就应该减掉那90%(例如:专注于可以通用的想法、系统、抽象概念和技术),只是别太在意那90%(就像我之前那样),或者找到一份我愿意牺牲掉那90%时间的工作,因为我觉得选择这份工作的原因很重要,或者给的工资很丰厚。

这条规则可能更局限于我个人,因为我已经换了一堆职业。对其他人来说,他们可以将技能从一份工作带到下一份。

规则3:将“学习时间”集中在复合上

复合是个很重要的概念,在复利中、摩尔定律中随处可见。它是关于良性循环的概念。因此在我有限的空闲时间里,我认为需专注于可能引发良性循环的东西。

良好的起点之一就是掌握快速打字的技能。在过去两个月中,我在keybr.com网站上花了些时间有条理地学习如何打字更快,这让我能够在相同时间里写更多内容,交流更多东西,完成更多工作,因为我在计算机上做什么都更快了。

建立持久的关系也是一项复合活动,因为你可以接触更多有助于你快速完成工作的人员。

消化媒体(书籍、博客等)并非天然的复合过程。唯有当你有某些方法想要反馈、消化,或将现有的知识与想法相融合时(比如本文中一些有价值的内容),作为读者,除非立即积极“处理”这些内容,否则很可能无法从中受益。

编程语言

这部分很有可能会充分暴露我的无知。

规则4:何时选用Java或C

Java是大型企业应用的理想之选,很难想象诸如亚马逊这样的企业使用其他语言。这是因为Java有库及社区的深层支持,且静态类型使得处理大公司内部天文数字级别的数据模型变得更加容易。

我将C#视为微软公司所推出的Java替代版,因此,如果我需要利用Java的某些优势,但又使用到了微软的生态系统,就会使用C#。

规则5:何时选用Python或Ruby

Python和Ruby对我来说非常相似。两者都是脚本语言,且都是动态类型,似乎是00年代最伟大的东西了。在速度比易读性或debug更重要时,可以选用它们。其次,针对机器学习或者人工智能应用程序,选用Python。

当使用Python时,应当启用类型提示会让情况更加清晰。

规则6:何时使用硬核语言

在我看来:Go、Rust、Haskell、Erlang、Clojure、Kotlin和Scala都是更为硬核的语言,其中我只用Kotlin发布过生产代码。

但假设一下的话,如果要构建全新的Web服务,我也许会用Go/Rust语言,因为延迟和性能在这种情况下比社区和库的支持更加重要。当我需要非常优雅或数学化的功能方法,却又无需大量的业务逻辑时,也许会选用Haskell或Erlang。至于Clojure,该何时使用我就不知道了,在我看来,如果我开始了解和喜欢Lisp之后,可能会用到它。我知道Clojure是一种可编译为JVM字节码的功能范例,但在这种情况下,我更倾向于使用Kotlin。因为Kotlin支持Java,对Intellij也有很好的支持。Scala也是一样,我可能首先会用Kotlin。

规则7:怎样使用Javascript

我写过的代码中,最糟的便是Javascript的。当时,我正为亚马逊开发移动购物体验,我的团队对JS框架知之甚少。因此我们换成了vanilla JQuery。起初非常简单,但之后我们有很多前端需求,很快管理前端状态完全成为了噩梦,想想看,组件消失又重现,而我们不知道原因,因此只能在控制台上注销掉所有的变量。

因此我是诸多体验极差的人之一,但我认为,这主要得归咎于我们自己。现在数年过去了,我的JS准则是:

1. 改用Typescript,让情况更清晰;

2. 尝试将更多逻辑塞入服务器端,如果前端不是太复杂,我会考虑类似Phoenix之类的框架,将所有内容全部丢到服务器端;

3. 如果需要前端交互性,使用类似Vue或React之类的框架;

4. 不要跳过单元测试。

规则8:何时使用C或C\++

我感觉:不是我们选择了C语言,而是它选择了你。有大量的应用程序——操作系统、语言设计、低级编程和硬件都必须使用C语言。

C\++则很有趣,对于诸如机器人技术、视频游戏和高频交易这样的应用来说,它极为有用。无垃圾回收功能对性能带来的收益,让它更优于Java。

规则9:如果想要测试服务器变更却不重建,请使用PHP或Hack

由于安全因素,亚马逊禁止使用PHP,但至少到2020年为止,其改进版Hack还在Facebook和Slack公司的后端上使用。

在此之前我从未考虑过何时应该使用PHP或Hack,也许是因为它们在亚马逊是一种禁忌。我知道Slack和Wikipedia都在使用这两种语言,Slack声称,它的编程环境极为开发者友好,例如,无需重启本地服务器就可查看变更,并web原生支持并发。

技术

规则10:何时使用无服务器函数

当有一个相对较小且较为简单的模块代码需要偶尔运行时,我会选用无服务器函数。

规则11:选用哪种数据库技术

当需要临时查询以及/或者需要ACID及事务支持时,请选择SQL,否则请选择no-SQL。尽管noSQL在处理事务方面,PostgreSQL(我对AWS Aurora的风格很熟悉)在可用性、可伸缩性和持久性方面表现都在改善,但传统上来说,noSQL更有优势。

测试

规则12:何时编写单元测试

只要缺陷的预期值并非微不足道,我都会尝试编写单元测试。预期值算法:“缺陷的可能性\*缺陷的成本”。由于无法真正精确计算出这些值,这算是一种逃避策略。但至少就我编写的代码和通常拿到的需求而言,缺陷造成高昂损失的可能性总会发生。

但是,每段代码都应当有个细致的单元测试,以证明代码是以可测试的方式所编写的,这一点非常重要。

不过,我并不认为需要囊括每行每段代码,除非你无法信任自己(或别人)在预期值方面的评估结果,那也可以采用这种策略。

规则13:何时编写集成测试

我对集成测试的定义是:当你调用不属于自己的代码时所使用的测试(而不是模拟)。

当我对不属于自己的代码不够信任时,都会尝试编写一个集成测试,尤其当这些代码有可能在我未知的情况下执行更改时。

规则14:何时编写端到端测试

我将端到端测试定义为产品模拟完整“用户会话”的测试——这里的用户可能是尝试对我的代码进行多次迭代,以完成某项工作的人类或者另一台计算机。这通常是规则12中所定义集成测试的超级集合。

1. 当我对产品的运作原理并不完全了解,也无法对变更进行完整的单元测试,希望能确定该产品的可运行性时,更像是“烟雾测试”;

2. 当我需要回归测试用例,以便在将来的重构中验证功能时;

3. 当结果难以提前预知,比如进行复杂的计算时,我想测试一些代码对其影响。

情况1应当避免,但情况2和3很难真正避免掉。

DevOps

规则15:何时安排专门的支持工程师

在亚马逊,默认情况下,你对自己的代码提供支持,因此如果你的某个系统出现了严重故障,你某个同事将会被派遣,并预期以通宵达旦的方式工作至问题解决。

可能很残酷。但在亚马逊公司(比如我现在的团队),当然还包括其他公司,会聘请专门的网站可靠性工程师(SRE)在正常的工作时间之外,在线解决生产环境中的严重问题。

在多年对付此类问题(并在我的团队内推动大家解决此类问题)之后,我逐渐相信:作为程序员,如果在非工作时间,有可能出现你无法控制的风险,那么你应当始终提倡有专职的SRE来解决问题。一个很好的案例:如果你继承了某人的代码,就可以解决现有的缺陷。

找到身处其他时区、通过训练足以支持你系统的人员往往并不困难,只需有资金支付即可。团队中的工程师需要共同努力,将这一观点传达给管理层,

安全性

规则16:如果你将所有的IT安全性问题推给信息安全部门(InfoSec),他们将对你提出严苛的规则

信息安全是一项艰苦的工作,博弈论想要生效,就会步入难以避免地过度谨慎小心。因此我认为,如果你至少能完成某些自己的安全保障工作,就能避免严厉限制的冲击。

一个很好的例子就是亚马逊内部wiki的迁移失败经验。早在2015年,亚马逊的信息安全团队就禁用了PHP。我们内部wiki使用的MediaWiki就是以PHP编写的,而内部wiki团队并没有质疑这个决定(尽管Facebook、WordPress、Slack公司都在使用PHP,Facebook还构建了清理过的Hacklang用以替代),而是执行了信息安全团队的建议。他们使用基于Java的替代品(Xwiki)来替换MediaWiki,最终使得相关团队用超过4个自然年的时间替代了24个开发年的产品,还不包括这次迁移对其他团队工作的中断——鉴于页面需要不断增加已迁移和未迁移项目。如果他们拒绝了PHP禁令,或者自己针对Hack进行一些研究,可能就会避免这场灾难。

设计与白板

规则17:让设计会话关乎输入,而非批准

很多会议的目的在于获得批准或者获得同意,除非万不得已,这种情况应当避免。你不需要获批,而是需要做出自己的决策,或者确定该从他人那里获得何种程度的许可。

与之不同,设计会议或对话应当是关于信息获取以及回答问题的。

项目管理

规则18:评估更多用于施压而非项目策划

我曾担任过开发者及尝试发布产品的产品经理两种角色,一直以来,我需要参与很多的评估会议。

人们常说,评估是用于计划的,是为了搞清楚某项工作所需要花费的时间,以便大家能够据之安排自己的工作。

.在我为期五年的产品发布经验中,回忆起来仅有一个项目是达到这个目标的——那是一个非常简单的安卓应用,没有外部依赖关系,技术上并不复杂,只有一个本地mySQL数据库,以及一些视图。在这个特定案例中,由于未知因素极少,评估非常准确,我们可以正确预期工作的完成时间,误差在1-2天之内。由于我们的期限定得非常严格,这次评估起到了很大作用。

这也是唯一一个我参与的项目里,可以正确量化速度,并正确推进里程碑的项目。

在其他所有项目中,评估的主要目的是施加压力:适时抛出类似“你说过只用5天”这样的对话,从而逼迫开发者更快更努力,同时也花费更多时间迅速完成工作,以免以后再遇到这样的对话。

我不反对有压力,但我认为,我们需要正确认识到:这才是评估的主要目的。

规则19:明确严格期限、软性期限、内部期限和预期完成日期之间的区别

严格期限:如果错过将对企业造成严重的不利影响。

软性期限:如果错过会令某些人看起来会很差劲。

内部期限:这是团队的内部目标,不会影响到团队外部的任何人。

预期完成日期:这是团队针对当下情况所评估的工作完成时间。

我见过很多将这些期限搞混的痛苦经历。任何时候,如果你拿到一个期限,请确认是其中的哪一个。当然,通常情况下,我们需要保证按时达成内部期限的工作,以确保在严格期限之前完工。但需要指出:让内部期限以严格期限的形式体现时,会对开发者造成压力,让他们延长工作时间。

需要牢记的另外一点:如果某个工程师给出一个预期时间,而其他人将其定义成严格期限(这种情况时有发生),这种做法是错误的。

规则20:当某人谈及敏捷时,请推进看板方法而不是Scrum

当某人讨论我们在做敏捷开发时,对我意味着每两周一次团队内部会议,仅此而已。

然后某些人可能会迷失在敏捷开发的两种风格:看板方法和Scrum里。在我看来,Scrum意味着“在那两周之内你需要完成特定的任务”;而看板则意味着“在两周之内完成你能完成的所有任务”。如果你不清楚所在团队遵循的风格是哪种,应当明确讨论,然后推进看板方法。考虑到评估的难度(见规则18),Scrum很容易导致在那两周时间里,你需要被迫加班以完成相应的工作。

原文链接:

https://muldoon.cloud/programming/2020/04/17/programming-rules-thumb.html

本文为CSDN翻译文章,转载请注明出处。

☞再见 Python,Hello Julia!

☞Go 远超 Python,机器学习人才极度稀缺,全球 16,655 位程序员告诉你这些真相!

☞你现在从事的程序员还有多久会消失?牛津大学研究员帮你算了算

☞一次对语音技术的彻底批判

☞后端程序员必备:书写高质量SQL的30条建议

☞到底是哪些人在玩链游?| 《区块链游戏玩家研究报告》