开发人员驱动的开发
注意:我于 2017 年底离开了 DirectScale。但是,我坚持我在这里描述的原则,并努力将它们运用到我的新工作中。
如果你喜欢这本书,你一定会爱上 《编程第一年》,这是一本为新开发者提供实用指南和建议的书。如果你正在考虑从事软件行业,请访问 https://leanpub.com/firstyearincode查看。
我所在的公司正在慢慢失去“初创企业”的地位。我尽量不去太过怀旧。毕竟,这意味着我们做得很好;最近几个月获得的一系列令人印象深刻的奖项和合同,意味着我们做得非常好。有很多值得感恩的事情。与此同时,很多事情也在发生变化。
随着这一转变的推进,我们不得不升级一些东西。我们聘请了一位首席技术官和一位企业架构师。“PCI 合规性”、“负载测试”和“根本原因分析”等术语正在成为办公室的标配。我们在部署生产代码时变得更加谨慎。我们正在成长。
但很多事情都保持不变——“在关键时刻,我们依然是同一家公司。我刚来的时候就了解到,对抗技术债务在这里是重中之重;现在依然如此。我们对代码审查的反主流文化态度依然强劲。我们仍然身兼数职。我们发展迅速,所以我们只能保留那些行之有效的方法——“一些做法正在被证明,而另一些则正在被摒弃。多亏了我们早期员工的远见卓识,前者比后者更多。自从我加入以来,我们的开发工作流程一直没有改变。它运行得非常好。”
不过,我还要更进一步。我们不会仅仅因为某种方法有效就一直沿用。实际上,只要你有无限的时间和资金,以及一些勤奋的开发人员,任何方法都能奏效。有效与否只是偶然。对我来说,更重要的是,我们的流程让我这个A型人格、执着的工程师感到安心。我们不会浪费太多时间,我们的代码库不会随着时间的推移而恶化,我不需要构建我讨厌的功能,我们的工作流程也不会让我每天都感到沮丧。如果你是一名软件工程师,你一定明白这听起来有多棒。
我认为我们的秘密配方是这样的:
我们做第二个。
一般人(包括开发者)倾向于将开发者视为代码编写机器,那些戴着耳机、滔滔不绝地写switch
代码的脑力劳动者。但这种刻板印象未能充分展现我们的潜力——否则,开发者的价值将完全取决于她的技术知识和打字速度。处于最佳状态的开发者就像软件行业的瑞士军刀——她们拥有富有创造力、洞察力和理性的思维过程,这使得她们在公司的任何讨论中都具有宝贵的价值。重视这一点的公司会拥有更快乐、更高效的开发者——无论你信不信,这些开发者不会把100%的时间都花在盯着代码上。DirectScale 在这方面表现出色。
好了,炒作到此为止:我们究竟在做什么?为什么我确信它代表了一套常识性的最佳实践——“不仅适用于我们,也适用于任何软件团队?”这个问题需要从多个角度来回答。让我们深入探讨。
我们永远不会做的事情
一般公司的“敏捷”工作流程如下:
- 身穿深灰色西装的人决定应该构建一个新功能。
- 他和另外两位高管聚在一起,漫不经心地决定了这个功能应该做什么,应该是什么样子。目前还没有人咨询过开发人员(稍后会详细介绍),所以整个想法简直幼稚得可怜。
- 他们结束谈话,给 Code Zoo 里级别最高的非开发人员发了一封邮件。他们漏掉了一些重要的细节。
- 这位非开发人员(可能是项目经理?产品负责人?Scrum Master?顺便提一下最新潮流)根据邮件内容、对公司使命的理解以及个人喜好,撰写了一系列业务需求。在接下来的两天里,这些业务需求神奇地转化成了一系列用户故事。
- 一位开发人员被分配到一个用户故事。如果他运气极差,就必须估算完成需要多长时间;这不仅需要高等微积分,还需要某种特殊的巫术。他立刻开始用代码思考,在停下脚步之前,已经写出了55行简洁优雅的C语言代码。大脑和键盘之间的连接就像尼亚加拉瀑布一样。这个功能突然就活了过来。他提交了一个拉取请求,然后像法国厨师一样亲吻指尖。
- 开发团队负责人审查了拉取请求并拒绝了它,并给出了 17 条解释性评论:此代码性能不佳、此方法未涵盖边缘情况、该类读起来像恐怖小说,并且最终的功能看起来与原始规范完全不同。
- 开发人员在与团队负责人反复沟通后,将代码重写了两次。两天后,他们都对结果感到满意。
- 代码于当天合并并部署到生产中。
- 几天后,高管们读了一套全新的发布说明,对冲刺期间发生的一切非常满意。其中一位高管感到疑惑,为什么他请求的功能没有实现。于是他又从第二步开始。
这显然不太好。它是《中国私语》(Chinese Whispers)、《你画我猜》(Pictionary)和《20个问题》(20 Questions)的结合体,这些游戏或许很棒,但并非经营公司的好方法。尽管如此,硅谷最优秀、最聪明的人都支持它,敏捷教练们也大力推崇它,它也是年轻团队的默认方法。
从第一步开始,我们可以做得更好。
开发人员的参与和支持
在 DirectScale,我们不会雇佣一群“创意人”来让我们围坐在一起,构思一些很酷的东西。我不想告诉你,“创意人”并不是一份真正的工作。抱歉。事实上,每个人都有想法。每个人都能为你的产品改进方向和解决的问题提供好的建议。作为回报,公司可以鼓励这些想法,也可以压制它们。大多数公司选择压制,尽管方式很微妙——将开发人员和设计师排除在产品愿景讨论之外,通过中间人传递指示和请求,或者将开发人员的反对视为“懒惰”和“抱怨”。
更好的方法是确保开发流程中每个阶段的代表都出席关于每个功能的每次会议,从开始到完成。与其等到下一个冲刺才发现你的功能在技术上不可行,为什么不现在就发现呢?没错,这意味着你的开发人员会花很多时间“AFK”(远离键盘)。但如果你邀请他们的反馈并倾听他们的意见,也意味着他们会认同——他们会致力于团队的共同愿景,并承担起功能的主人翁责任,这意味着他们能够更快、更好地完成任务。对于更大的功能,你需要更多的认同,这意味着需要更多的开发人员参与。
正如我提到的,这也能避免你浪费几天时间构思一个开发人员无法(或不应该)实现的功能。正如我们大多数人所了解的,看似简单的功能有时可能极其复杂、不可能实现甚至违法。没有人喜欢在功能发布日期已经确定之后才发现这一点。
我最近参加的一次会议是设计工作室会议,讨论一个大型功能集,这个功能集未来几年可能会成为 DirectScale 最大的收入来源。这是我们全年讨论的最重要的产品垂直领域。猜猜都有谁参加了?
- 用户体验设计师
- 三到四名开发人员
- 平面设计师
- 我们的项目经理
高层并没有详细描述我们要构建的功能,也没有一位首席或副总裁在场。全靠我们自己。这又有何不可?我们做好了准备;我们的用户体验设计师和项目经理都有行业经验,他们已经采访了几位可能使用该功能的客户。高管团队表达了他们的期望(但并未试图控制创意过程)。我们已经进行了几次讨论,确定了待解决问题的范围。毕竟,我们才是最终要构建这个东西的人。
两个半小时后(会议比平时长,但很值得),我们拿出了一些草图,对拼图的第一部分达成了共识,每个人都对自己的想法能够融入到最终成果中感到满意。就这样,我们的产品诞生了。
开发设计(反向代码审查)
一旦我们的想法变成了原型,我们就可以开始编写代码了。但我们暂时还不会打开 IDE。
瞧,软件构建是一门失传的艺术。《代码大全》的作者史蒂夫·麦康奈尔用几章充满激情的篇幅,探讨了业务需求的提出和代码编写之间的差距——“在他看来,办公室里最聪明的架构师应该在这个差距里,为即将编写的每个类、接口、交互和数据点绘制详细的蓝图。在麦康奈尔看来,只靠用户故事或设计来编写代码,就像没有蓝图就建造摩天大楼一样。”
但不知何故,大多数公司已经忘记了如何规划。
问题出在我们示例敏捷流程的第 4 步和第 5 步之间。在用户故事定义完毕、开发人员开始敲击键盘之前——“发生了什么?大多数情况下,什么也没发生。”
经验丰富的开发人员或许能够预见完成简单任务所需的所有工作。但即使是我们当中最优秀的人,也会遇到意想不到的障碍。我们都经历过这样的时刻:就在我们编写最后一行代码时,突然意识到我们的逻辑中没有考虑到所有的情况。
然后,当你发现团队的新成员写了一整个类来解决一个问题时,那种沮丧的感觉油然而生,而这个问题在代码的其他地方已经有了标准的、可复用的解决方案。如果在开始编码前花五分钟时间分享知识,就能避免三个小时的重复工作。
如果代码没有按计划进行,我们所有精心设计的流程都无法成功:标准被忽视,可重用性消失,代码随着时间的推移变得更加分散,错误百出。短短几年内,你就得处理遗留代码(不寒而栗)。某些问题会在代码审查中暴露出来,但到那时,很多东西都白白浪费了:数小时的开发时间、数个问题解决周期,以及开发人员的热情和奉献精神。
所有这些问题都可以通过史蒂夫·麦康奈尔 (Steve McConnell) 在 1993 年提出的建议来避免(或至少缓解):提前规划。
在 DirectScale,我们彻底颠覆了代码审查的模式。我们不再事后审查代码,而是提前确保其正确性。我们提前规划。我们称之为“开发设计”,它很像在任何人编写任何一行代码之前进行的协作式代码审查。它的工作原理如下:
- 创建了一个用户故事。
- 指派一名开发人员来设计故事所需的工作。
- 开发人员会查看需求,深入代码库,查找任何有用或相关的内容,研究可能需要的库和技术,并撰写一份详细的、分步的描述,说明如何编写完成用户故事所需的代码。最终的文档(开发设计)包含所有最终会在代码中出现的变量名称、缓存技术、类、接口和交互。在棘手的情况下,开发人员甚至可能包含几行伪代码。
- 开发人员安排与团队其他开发人员开会。他们会一起审查开发设计,并根据需要进行修改,提出替代方案,分享知识,并做出架构决策。
- 团队按照开发设计中规定的任务完成任务。如果出现问题导致无法完成,团队会当场讨论并决定如何处理。
- 大多数情况下,不需要代码审查。代码会按原样合并并提交给 QA。
通过这种方式,我们避免了惊人的反复。之前在一家公司,在一位特别挑剔的团队领导手下,我平均每个拉取请求都要重写近五次。现在我平均每次都不需要。提前规划可以确保事情一次性完成。
20% 的时间(不是Google 那种)
在 DirectScale,我们不允许技术债务不断累积。技术债务会随着时间推移而增长(就像普通债务一样),当达到临界点时,必然会破坏用户体验,惹恼客户。更糟糕的是,它会让程序员感到沮丧,并可能给任何接触受影响代码的人带来严重的“搞什么鬼”效应。
然而,解决技术债务是一项违反直觉的活动。首先,它看起来没什么特别。如果一位高级开发人员花了一周时间偿还技术债务——重构代码、拆分类、平滑临时代码、处理边缘情况——他能拿出什么成果呢?其他开发人员可能会欣赏这种变化,但任何头衔中带有“经理”一词的人都被迫相信。没有任何新内容可以展示给客户,没有修复任何紧急错误,应用程序的速度甚至可能没有明显的提升。如果产品负责人在你的发行说明中看到“已解决技术债务”这句话,他们怎么知道你不是整周都在玩纸上谈兵呢?他们不知道。
但“债务”这个比喻在这种情况下是正确的。假设你有15,000美元的信用卡债务。如果你用接下来的三张薪水来偿还这笔债务,你还能拿出什么成果呢?真的没什么——“没有新家具,没有豪华晚餐,没有修理炉子或汽车。但你比以前好多了。你最好知道这一点。”
为了防止管理人员和开发人员过于纠结于截止日期和功能而无暇投入到健康的代码开发中,我们严格执行最低标准:至少20%的时间用于对抗技术债务。这意味着每五个用户故事中就有一个。我们每周都会进行几次标准化、重构、负载测试、研究和创建开发者资源。我们做的事情客户永远都不会知道。但他们知道的是,我们的软件比他们曾经使用过的任何软件都更先进、更可靠、更令人愉悦。而且他们也敢于直言。
虽然我们为解决技术债务所做的工作并不总是令人兴奋(尤其是重构,它是开发人员所做的最具挑战性和最繁琐的工作之一),虽然它不像功能驱动的任务那样能带来即时的满足感,但它仍然令人欣慰。花一两天时间调整和改进纯代码的感觉就像感冒后恢复一样:之后的世界似乎更加光明。回头看看,你会发现你的代码比以往任何时候都更加合理和易于维护——“它看起来就像教科书上写的那样”。你的努力在未来的几个月里得到了回报。使用得到妥善维护的代码工作总是让人感到轻松自在。
故事去专业化
初创公司以要求员工身兼数职而臭名昭著。有些公司把职位头衔视为事后诸葛亮;在不同时期,你可能最终会(就像我一样)担任后端开发人员、前端开发人员、质量保证工程师、技术作家、西班牙语翻译、可用性面试官和打印机支持技术人员。有些人不喜欢小公司的这种特点。我却喜欢。
在我们的团队中,我们鼓励去专业化,直至单个用户故事。在一些公司,这被称为“蜂拥而至”。我们的方法是这样的:当一个开发人员准备好执行另一个任务时,无论他是否参与了用户故事中的其他任务(以及他是否知道如何执行),他都会被分配到优先级板上最优先的任务。我们的团队负责的是产品,而不是编程语言——“如果你在我们雇佣你时了解 T-SQL、C#、.NET、JavaScript、Angular.JS 和 SASS,那就太好了。如果你不了解,你也可以在完成需要这些内容的任务时学习。”这使得我们更像工匠,而不是流水线工人。我们的目标是确保我们每个人都足够了解源代码的每个部分,以便有效地使用它,尤其是在紧急情况下。
这也确保了我们的团队能够通过“公交车测试”:如果明天团队中某个成员被公交车撞了,我们还能顺利继续工作吗?还是说,我们得指派一个人去承担一项艰巨的任务,去弄清楚如何维护他们管辖范围内的代码?公交车测试在 DirectScale 尤其重要,我身边都是才华横溢、能力出众的同事,他们对我几乎不熟悉的领域充满热情。但我相信我们能通过。即使我们最聪明、最勤奋的员工突然去世,工作也会继续进行。而且没有人会那么想念我(开玩笑的,开玩笑的)。
午餐袋和专业发展
DirectScale 鼓励持续学习和改进的文化。这不仅仅是赞助的 PluralSight 会员资格或公司图书馆。我们认识到,最好的老师是与我们一起工作的人,最好的课堂是以人际互动和讨论为教学计划的课堂。为此,我们每月会抽出一两次时间在小组环境中互相学习。我们称之为“棕色袋子”(brown bag)。
这通常需要公司里某个比我们其他人更精通某项技术或技能的人来做演示。我们开过午餐会,主题五花八门,从 CSS、团队合作、睡眠习惯到 SQL 调试,应有尽有。任何话题都可以讨论。
就像去专业化一样,这有助于我们通过公交车测试。一个真正充满热情的人在一小时的非正式会议中能够传达的信息量令人印象深刻。
它还能提升开发者的幸福感。开发者在学习和成长的过程中最快乐。我工作中最美好的时光——“那些我满脸笑容地回家,对工作充满热情的日子”——“就是我学习了一个新的框架或概念,并开始好好运用它的日子。我们开发者从学习新事物中获得巨大的兴奋。
为什么这么高兴?
我花了很多时间详细阐述那些让我在工作中感到快乐的事情。虽然我试图通过指出我们工作方法和理念的所有其他好处来平衡这一点,但我还是有点担心有人读到这些后会完全忽略重点。在某个公司,某个地方——“我的很多开发人员朋友似乎都曾在这家公司工作过”——有一群中层管理人员,他们还停留在1906年,满脑子想的都是“谁在乎你快乐不快乐?”对他们来说,开发人员就像奶牛。你把他们关在笼子里,榨取他们愿意写的代码行数,然后就把他们解雇。如果一个人辞职,只要薪水足够诱人,另一个人就会接替他。
如果你不幸管理了具有这种态度的人,我建议你解雇他们。
这里有一条新闻:快乐的 开发人员 工作 出色 。事实上,这几乎是必然的结论——成功的公司问的问题不是“我们应该善待我们的开发人员吗?”而是“我们如何才能让我们的开发人员更快乐?”
另一方面,不快乐的开发人员会在一段时间内编写出糟糕的代码,然后辞职。如果你不把开发人员的幸福感作为全公司的优先事项,最终你将被迫将开发人员的流失视为一场全公司的危机。
我意识到,作为一名开发者,说出这些话符合我的个人利益。你可能会说我是个“天后”。也许你是对的。但如果我是个“天后”,那我就是那种能用十个指尖创造出优秀软件的“天后”。现在像我这样的“天后”的需求量非常 大 。而我远不是这个领域里最优秀、最聪明的人。
简而言之,试图像优化卷烟厂的装配线那样去优化开发人员没有任何好处。你必须让他们按照自己的方式行事。但你会对结果感到满意。快乐的开发人员会编写出优秀的代码。编写出优秀代码的开发人员也会感到快乐。
结论
我只是让你大概了解了在一家真正懂软件开发的公司工作是什么样的。我希望你能看到更完整的全景。总的来说,我做程序员的时间并不长,但它彻底改变了我对这个行业的看法。
你可能已经知道,开发人员是招聘人员严密盯防的对象。我经常收到招聘人员的来信,几个月前,其中一位甚至邀请我一起吃午饭。我特意问了他几个简单的问题:
- 开发人员在多大程度上参与了您的设计和发现过程?
- 您如何处理技术债务?
- 贵公司的代码审查进展如何?
- 您认为您的代码库中有多少“坏代码”?
这让他很不舒服。但(值得称赞的是)他对我很坦诚:这些在他公司并非优先考虑的事情。我谢过他请我吃午饭,并告诉他我没兴趣再继续聊下去了。
听着:如果你还觉得桌上足球和可乐能让开发者开心,那我得告诉你,它们根本不会。当然,这样的福利确实不错。但真正让我们开发者开心的是每天解决各种挑战,编写熟悉、编写精良、充满我们引以为豪的功能的代码。
如果你不能为我们提供这些,那么你实际上就没有什么可以提供的了。
鏂囩珷鏉ユ簮锛�https://dev.to/isaacdlyman/developer-driven-development