软件开发范畴素来有10倍开发者的说法,但关于有志向的开发人员来说,在提高开发、架构能力的基础上,练习自己站在产品的视点考虑问题,将产品打造得更为符合客户和运维的需求,或许比10倍效能的个人开发者能够发生的价值更大。原文: How to Outperform a 10x Developer
“10倍开发者”这一说法起源于Jeff Foster写的一篇文章,他在文章中对比了超强代码能力和专心于产品的价值。
站在DevOps(覆盖了从开发到运维的全方位协作)的视点来看,专心于产品要胜过编码技能,由于有时候不写新代码是对产品最好的决定。
本文供给了具体比方,能够更好了解出产体系怎样改动软件开发人员的人物,并显著改善规划体系和编写代码的办法。
当质量不够时
当然,高质量的代码和对技能的锻炼仍然十分重要。软件开发人员应该遵守良好的实践,例如自动静态检查、代码审查、单元测试以及许多其他办法。虽然如此,快速编写高质量代码只是将体系投入出产并坚持其活力所需的一切使命的一小部分。
从这个含义上说,安排不应该花费太多资源来寻觅和培养10倍开发者。首要,他们或许不是真实的10倍开发者。其次,继续的软件开发有必要包含支撑东西,如规划文档和运维程序,这些文档有必要与运用它们的人一同协作不断被审查和更新。咱们能够简化和谐活动,但基本的人际交互和作业流几乎不会以10倍的速度发生。
9月22日更新: Hajime Vukelic在这篇文章中添加了一条评论,指出我的说法听起来像是说优秀的个人表现是不或许或不受欢迎的。我仍然以为这在DevOps实践中是困难的,但他深思熟虑的文章我以为是对这一主题的极好的补充,文章题为”What’s a high-differential developer”。
你希望开发人员能够达到更高的水平(比方1.2倍开发者?),以便其他团队成员能够了解和吸收更高效的技能和行为。
第一课 — 优秀需求花27倍乃至更多的时刻
我指的”时刻”不是指”几十年经历”(当然这也有协助),而是指做伟大作业所需的实际时刻。
即便是最有才华的开发人员,也会对从原型发展到可继续的出产体系所需的时刻做出糟糕的估计。我有必要着重”可继续的”这个词,即随叫随到的轮班工人也能够产出效果,[即便不懂代码的人也能够解决问题](sourcepatch.blogspot.com/2021/09/ask… “Should (only “即便不懂代码的人也能够解决问题”) developers be on-call?”)。
我最喜爱的估算产品特性总本钱的办法是创立作业原型,然后将原型所花费的时刻乘以27。这是对的,由于假如我需求两天时刻来开发一个原型,那么整个团队或许需求将近3个月(2×27=54个作业日)的共同努力才干将其投入出产。
9月22日更新: 用户Liquid Analytics在评论区提出了一个很好的观念,即27倍乘数或许成为有含义的发展的阻碍要素。我应该说到,这个主意是运用现代”test in production”办法来布置原型,比方利用暗启动或特性开关进行依据主干的开发。
为什么是27倍?
Frederick Brooks Jr.在《人月神话》中解说了第一个9倍,这是他以书本方式宣布的关于软件开发的一系列具有里程碑含义的文章。
第一个3倍乘数是从可运转的代码(书中运用术语”program”,这是其时的特点)到牢靠的应用程序(书中运用术语”program product”)的本钱。
第二个3倍乘数来自将牢靠的应用程序转换为体系(“system product”)所需的额定测试。
Brooks介绍了创立交付给客户进行内部布置的软件的各个方面(这是其时IBM业务模型的特点),因而扫除了与运营方面相关的本钱,为此我添加了终究一个3倍因子(这是依据我在运维工程方面的经历,有或许你的乘数会有所不同),以将体系转变为可运维的依据云的服务。
终究一项乘数包含下列开发活动:
- 测量体系的可观测性
- 依据体系规划编制运维规矩
- 继续布置流水线的开发和保护
- 与其他云供给商服务的集成测试
结合一切乘数(3x3x3),咱们将原型投入出产的本钱添加了27倍。
重要原因: 虽然经历丰富的开发人员或许不会低估新功能的规模,但任何超出2倍或3倍的要素都肯定会在整个团队中发生难以处理的意外,更重要的是,会糟蹋咱们验证新功能所需的时刻,然后给运维团队带来噩梦。
第二课 — 运维是一项工程而不是艺术
不管怎样,艺术都有其方位,体系的某些旮旯或许看起来即聪明又精美,但终究方式服从功能,出产体系的功能是运转满意需求和本钱方针的软件。
本节将介绍在运维中获得的经历教训,以及怎样影响规划和编码活动,这部分作业占了27倍倍数的一部分。
这一节没有包括代码开发之外的一切规模,然后防止文章过于冗长。
更多的组件,更多的本钱,检查每个人的预算。 在规划和架构时需求考虑运维本钱是我在运维期间学到的最重要一课。体系中的任何新组件都会改动运维该体系的本钱结构,因而问问自己,该组件是否减少了比添加的本钱更多的本钱,并准备好抛弃在体系中添加一些看起来十分风趣的东西。
毕竟,在同一个世界里,首席财政官们(正确的)告知你,添加收入比削减开支更重要,开发人员将其诠释为将一个50毫秒的SQL查询笼统为微服务包装的一系列分页RESTful调用(真实故事)。
我并不是说要采取相反的办法来改动,但这是一个需求找到协作办法的范畴,或者至少要与运维团队进行协商。
全局状况和健康检查点。 假如发生停机作业,没人能够在缺少体系状况的状况下做任何作业,特别是在具稀有百个组件的微服务架构中。
出产体系需求总体运转状况检查点,该点集合了来自各种依靠项的运转状况。其思想是运维人员能够快速评估(1)体系的哪些部分不起作用(2)哪些依靠项不起作用。后面会说到”为什么”需求这样的检查。
我在关于Kubernetes容器的readiness和liveness的文章中列出了关于规划健康检查点的主张,那篇文章中的大多数主张也适用于非Kubernetes体系。
从读者的视点记录过错。 一旦运维人员意识到体系不完全健康,下一步便是了解是什么原因,以及怎样修复。
有些作业应该会发生,但却没有发生。从阅览日志音讯的人的视点来看,最有用的日志音讯遵循如下模板:
[ERROR|WARNING|INFO]: [Component X] attempted to [take action Y], which returned [response Z].
这种格局乍一看好像很明显,看起来像常规的主谓宾结构,但最重要的是术语:
- “Component X“是否存在于体系文档中?
- “action Y“对读者来说容易了解吗?
- “response Z“是否在故障扫除手册的某个当地说到?
我读过很多过错音讯,很感谢有人花时刻把它们添加到代码中,但我对其间引证的只对代码作者有含义的文件名和库调用犹豫不决。这些内部引证应该放在专用的盯梢文件中,或者添加”debug”前缀标记,以便于过滤。
终究,每条日志音讯都有必要导致一个明确的解析步骤,该步骤不触及联系音讯的作者或阅览源代码。
编写体系文档: 编写文档迫使咱们将对体系的了解构建为一种新的媒介。除了有必要告知人们怎样装置、监控、保护或扫除体系故障之外,该活动还为体系带来了许多好处。
写作行为要求作者对体系中难以解说的方面进行思考。
一般,这种困难或许表明潜在的规划缺陷,例如难以解说一切组件的正确装置顺序。其他时候,这种困难或许是由于产品的”待开发”区域需求为读者供给一大堆伪代码指令(“…然后点击这里,键入这个,等候几秒钟,然后一个面板将弹出,找到一个名为…的按钮“)
假如处理妥当,文档还能够作为协作者的集合点,这些协作者或许乐意奉献他们的知识,但没有时刻去弄清楚怎样做到这一点。这些类型的奉献关于整个生态体系(开发人员和用户)来说是巨大的出产力提高,假如不加以记录的话,往往会丢失在团组和私人对话中。
时刻框调用长途组件。 在分布式体系中,咱们比依靠长途代理更了解怎样快速牢靠的呼应。虽然如此,咱们经常在客户端库和实用程序中运用默认的超时设置,而不加考虑,由于咱们以为开发人员已经找到了适用于每个人的奇特设置。
这是一个常见疏忽,由于库和实用程序都带有合理的默认值,体系采用了最新的规划和运维技能,以获得最大的可用性。对体系结果的过错信赖一向继续到其间一个体系发生故障,导致组件无条件等候TCP超时达2小时。
总是在代码中寻觅长途调用,并保证知道它们的约束,以及代码怎样处理这些约束:
- 最大衔接呼应时刻
- 最大恳求呼应时刻
- 最大重试次数
对任何体系来说,为长途调用创立有效的重试战略都是一项受欢迎的改进。虽然如此,仍有或许掩盖对迫在眉睫的问题的可见性,例如掩盖呼应时刻的继续恶化,直到它们终究超过最大约束,这将我引向下一点。
遥测、可观察性和分布式盯梢: 处理停机比检查体系状况和日志条目要杂乱得多。除了处理中止之外,还有更多的操作,例如主动检查体系对内部衡量、盯梢和日志条目的遥测。
许多平台已经在源代码中运用最少的指令生成了很多遥测数据。可是,仍然需求将很多特定于遥测的代码与源代码混合在一同,尤其关于衡量(metrics)来说。
另外,保证你(和其他开发人员)能够定期拜访体系操作中运用的遥测结构的本地设置。许多结构支撑在作业站或免费试用的依据云的帐户中本地履行,从本地环境无缝过渡到长途环境的一致设置需求开发、验证、文档编制和保护。发明这样的环境十分风趣,但也需求花费时刻和金钱。
再怎样着重也不为过,即便是最有经历和自傲的开发人员,在检查他们的代码遥测时,也总会学到一些新的或令人惊讶的东西。
更进一步,与运维团队协作,保证与运维团队共享数据,特别重视数据匿名化和拜访等方面。
重视行列体系。 编写行列体系很风趣,规划架构图是令人兴奋(和诱人的),可是大多数人严重过错的判断了在体系中添加行列方式的本钱。
我知道行列体系有一些合适用例,比方很多业务(例如每天稀有百万条音讯),其间调用组件不能等候呼应,而只关怀业务终究在合理的时刻内得到处理。
可是,假如不处理这些用例,或许需求仔细考虑是否需求将异步音讯处理包含到体系中。这种通信方式添加的本钱贯穿音讯出产者”A”和音讯消费者”B”之间的整个业务业务。以下是关于这种额定杂乱性的几个比方:
- 体系办理员用于处理行列大小超过某些约束的运维流程。
- 处理过期音讯的额定规划和代码。
- 处理过期后发送到死信行列的音讯的操作过程。
- 扩展体系以办理死信行列。
- 处理跨音讯传递的业务业务的分布式盯梢。
第三课 — 大杀四方:编码、构建、支撑、运维
虽然长时刻职业生涯或许会逐渐教会你DevOps实践的不同范畴,但你能够经过有意的在开发、集成、支撑和运维之间轮换来加快生长。咱们的主意是学习事物是怎样作业的,以及怎样构建在工程周期的每个重要范畴都能很好作业的软件。
一旦你了解了这些范畴的人员和作业流程,就更容易在核心专业知识之外做出奉献,减少技能和社交摩擦。
处于职业生涯中期和高级的开发人员或许不倾向于改动作业人物,但经历使他们能够更快学习。几个星期的暂时轮岗、共享项目,乃至是处理客户支撑和作业报告都能够起到同样的作用。
事例研讨1(构建)
在之前项目中,咱们有一个团队主要负责演进和保护构建体系。在本地作业站上构建(编译和打包)整个代码库大约需求两分钟。相比之下,在构建周期中,相同的操作花费了看似永恒的15分钟。
构建团队之外的一名开发人员花了一个下午的时刻将各种日志条目添加到构建脚本中,以阻隔问题,将或许的原因缩小到构建将已编译二进制文件写入磁盘的步骤。在构建体系中,磁盘写操作好像比在本地作业站中花费的时刻要长几个数量级(是的,构建机器有SDD存储:-)
构建团队分析了这些发现,并尝试了不同的代替计划(其间一些计划超出了原始开发人员的Unix技能集),终究的解决计划是添加虚拟机上的内存分配,并将每个构建的暂时目录移动到内存文件体系(tmpfs)。
事例研讨2(运维)
我曾经继续几个月办理整个安排(几百人)的PagerDuty升级战略和警报规矩。有时,由于假期安排,当收到紧迫音讯时,需求跳过我的直接处理规模触发警报。
在按下按钮之前,我总是会问几个问题,比方:
- “这些发生新警报的组件是什么时候布置的?”
- “我在描述中没有看到剧本链接,运维团队知道去哪里找吗?”
在不触及偶尔混淆的令人困惑的答案的状况下,这个(兼职)使命教会了我宝贵的经历,包含办理体系中警报类型总数的重要性,向出产体系添加新组件的本钱效益,以及让运维团队参加架构决策的肯定必要性。
第四课 — 有意识的学习:在每一项使命中学习
在这一点上,你需求知道怎样保证时刻来编写用于出产的代码,以及需求在代码中包含的内容。
这是一个很长的清单,虽然有[“1万小时”规矩](www.edsurge.com/news/2020-0… “”1万小时”规矩” “”1万小时”规矩”),但你不会想要等上几十年才干自可是然获得这些技能。
咱们总是在履行使命的过程中学习一些东西,但刻意学习意味着不仅要完结作业,还要弄清楚为什么某些作业会起作用,以及怎样改进。
查找网络或许会给你某个特定问题的精确答案,人们能够经过这种办法学到很多东西,但经过有意识的学习,咱们想要的是逾越现成的解决计划:
- 阅览。 假如解决计划触及结构的方式化解决计划,例如Terraform的一组特定资源,请回来阅览这些资源的完好定义,并或许阅览来自同一供给者的附近资源。
- 假如解决计划触及具有特定参数的实用程序,请回来实用程序手册研讨这些参数,并阅览其他参数。咱们的主意不是记住它们,而是在脑海中索引它们,特别是关于”awk”这样的东西,其手册能够是一整本书。
- 解说你学到了什么。关于源代码,请拿出”橡皮鸭”,并向一个无生命的物体解说源代码。关于概念,你乃至能够不去找别人,而是运用费曼技巧,假装你是在向一个孩子介绍这个概念。
- 写作关于主题的文章。写作是一种更有意识的学习方式,协助你稳固和扩展对一个概念(或许是写一篇文章)、相关概念(运用技能论文之类的东西)或整个范畴(例如写一本书)的知识。写作远远逾越了学习,或许更有助于在头脑中安排相邻的知识。假如你决定从事这项令人兴奋的活动,一定要阅览海因里希哈特曼(Heinrich Hartmann)的《为工程师写作》。
“阅览产品攻略?谁有时刻读?”
我意识到这是一个用谷歌查找”怎样让这个过错信息消失”的年代,这在时刻紧迫的时候很有含义。不过,你从这些捷径中学不到多少东西。
在这里,我有必要引证史提芬金的话,他是有史以来最成功的小说作家之一,他给有志向的作家供给了这样一条严厉的爱的主张:
“假如你没有时刻阅览,你就没有时刻(或东西)写作。便是这么简略。”
假如你没有从时刻表中抽出时刻来探究项目中运用的技能,并对其进行扩展,你就会约束自己只学习满足完结当前使命的技能。当你周围的人以为你只能担任同样的使命时,这种动力就会自我强化。用不了多久,这些假设就会被证明是正确的。
依据不同状况,”挤出”时刻或多或少具有挑战性,但意识到这一点是一个起点。有时你或许会不断加倍承当重复性(但有价值)的使命,由于这样更舒畅。在其他时候,安排或许会对或人比其他人更有效的做重复的作业感到满意。不管状况怎样,首选需求知道到你无法从每项使命中学习新东西。
定论
DevOps实践包括了许多不同且广泛的流程,使得人们专心于特定范畴,如软件开发、继续交付或运维。
有时,在人们有时机探究其他范畴之前,爱好和方针就会缩小,所以要抵抗在职业生涯前期专攻的冲动和压力。作为安排,在员工或许长时刻呆在一个职位上所带来的出产力与日本式的年度轮换办法(或许不是固定的时刻表)的好处之间获得平衡。
在职业生涯前期,与办理团队一同在编码、交付和运维方面进行”实习”。这种全面的经历是十分宝贵和稀有的,不管是作为程序员、体系架构师、用户体会规划师、技能客户经理、基础设施工程师,或任何其他你或许喜爱的人物,都将协助你在任何你挑选奉献的范畴倍增你的潜力。
乐意从不同视点了解是什么让产品变得更好,并将这些经历教训融入日常日子中,这是一种超级力量,远远超过了一个实际的10倍开发人员在利基范畴所能集合的力量。
归根结底,这些教训来自个人经历,每条道路都是不同的,欢迎供给反应。