Press "Enter" to skip to content

创业公司CTO手册(三)—— 技术团队管理

作为技术领导者,您的成果将取决于团队的表现,因此您需要确保整个团队运行良好。什么是良好的运行将因团队和情况而异,但与高绩效相关的一般模式和趋势是存在的。在本节中,我旨在就所有技术领导者共同面对的情况提供指导。

技术文化和一般理念

我鼓励所有领导者采用被称为“仆人领导”的一般领导风格。作为仆人领导者,您的主要关注点是为团队的需求提供服务。这意味着专注于赋权他人,建立透明、沟通、协作和成长的文化。在思考团队、文化和日常决策时,请问自己哪个选项使团队能够发挥出最佳工作能力,从而为业务提供最大的价值。

技术文化的十个基石

  1. 将团队时间花在对业务有意义的事情上

一般来说,您希望您的团队将时间花在对业务有所推动的事情上。作为技术领导者,您的责任是创建一个环境,让工程师能够持续地将精力集中在这些方面的努力上,保持一致性并最小化干扰。这个框架可能似乎很明显,但正确使用时,它是一种强大的决策工具。

例如,假设您的团队正在讨论使用现成的后端框架还是从头编写。人们可能会列举一份细致的利弊清单,讨论从头构建带来的灵活性与使用框架带来的更短的第一次部署时间之间的取舍。在这个假设的情况下,您的业务实际上需要的是迭代前端并优化客户旅程,因此在后端花费的每一刻都是前端推进所少的一刻。如果开箱即用的解决方案足以支持前端迭代,即使您在十八个月后必须放弃框架并使用自定义解决方案重写后端,现在快速前进并找到产品市场配对的机会,这将使您的业务有权在将来进行重写。

  1. 在可靠工具处使用,重点创新

也称为不要重新发明轮子,以及站在巨人的肩膀上,这里的想法是在可能的情况下使用现成的组件(库、云服务、应用、软件包)。在使用现成组件时,存在着使用的便利性和将解决方案与实际问题相匹配之间的取舍。我认为,在现有实施方案已经存在的大多数情况下,取舍更倾向于使用现成的服务、库或应用。

在您最终需要重写或对依赖项进行大量定制的罕见情况下,您对现成工具的使用经验将在影响和加速自定义构建设计时非常有价值。

  1. 自动化提高效率

作为团队的架构师,您的目标是确保团队花费尽可能多的时间编写为业务创造价值的代码。开发者在日常工作中会做一些消耗时间的任务,这些任务虽然对编写代码来说是必要的,但本身并没有增加业务价值(例如,复制生产环境、在本地运行代码、运行测试套件的方法、在云中设置功能分支环境、查找测试覆盖范围之外的错误等)。

这些类型的任务会对整体生产力造成持续影响。您可以通过自动化这些任务来避免付出代价。鼓励团队记录每当他们花费超过三十分钟在非生产性技术工作上时,并在流程中提供自动化这些任务的空间,这样就不会再浪费他们的时间。

  1. 频率降低困难

马丁·福勒在《频率降低困难》中详细解释了“如果感到困难,就多做几次”的理念(ctohb.com/fowler)。福勒认为,团队认为痛苦、易出错或者对团队来说成本高昂的任何流程或任务,都是该任务不够发展的一种标志。在没有负面压力的情况下,痛苦的技术任务往往是最后一个自愿完成的任务。结果,这些任务被忽视了,随着时间的推移,痛苦程度变得越来越严重。然而,如果您的团队文化强调优先处理这些痛苦的任务,那么就会投入更多的精力自动化、文档化和改进这些任务,从而使它们最终变得不那么痛苦,甚至完全自动化。正如福勒所指出的,更频繁地执行任务也提供了更多的反馈,并通过实践建立技能,所有这些都进一步降低了任务的困难和痛苦。

对于许多团队来说,将代码发布到生产环境是一个常见的痛苦任务。发布代码可能需要数小时的时间,因此发布频率很低。然而,如果您的团队认同“如果感到困难,就多做几次”的理念,您作为技术领导者将推动团队定期以更快的间隔进行发布。如果您从每周发布开始,那么在第一周,团队会感受到痛苦,第二周和第一周一样痛苦,但也许工程师们会注意到一个可以自动化部署的部分。到了第三、第四或第五次发布时,您很可能已经有了一个全新的脚本和基础架构来让代码上线,从而使您能够加快发布频率为每周两次。一段时间后,您将能够一键发布代码。每天发布一次以上被称为持续部署(参见连续部署,第 216 页)。

  1. 标准化请求评论(RFC)流程

RFC(Request for Comment,意为征求意见请求)是一份概述的技术想法、流程或规范的文档,编写目的是为了同行评论和后续采纳。您熟悉的大多数协议都有相关的 RFC,例如 HTTP 的 RFC 2616,或 DNS 的 RFC 1035。同行评论、后续采纳和标准化的想法对于准民主方式进行技术决策并获得对结果的认可是一个强大的工具,它也可以作为与团队合作的一个很好的工具。

我建议您形式化一个 RFC 流程,并提供一些指导,说明应对哪些决策进行 RFC 流程。

形式化过程可以包括一个简单的检查列表和一个模板文档,其中包括放置文档副本的位置、如何收集反馈/评论以及投票、最终确定和标准化文档的过程。

我的建议是利用你手头的工具,例如在源代码控制中创建一个Markdown文档作为RFC模板。新的RFC将是该仓库上的一个pull request,引入一个新的Markdown文件来提出建议。然后,自然而然地收集批准的投票作为对该pull request的批准,RFC最终在该pull request合并时完成。或者,如果你已经建立了一个内部wiki,你可以在那里创建一个RFC,并使用wiki的评论系统收集反馈意见。

你还应该对需要进行RFC决策的类型设置明确的期望。我建议将其限制为高层流程、技术观点和文化,而不是用于工具选择或系统架构。以下是一些适合使用RFC的好例子:

  • 统一命名约定 (主分支 vs. main分支,白名单/黑名单 vs. 允许列表/拒绝列表,各种情境下的驼峰命名法 vs. 蛇形命名法)
  • 代码格式化程序/静态代码分析的使用
  • 会议节奏/议程/文档
  • 单一仓库 vs. 多个仓库
  • API设计的观点/哲学

我鼓励你在RFC模板中加入一个部分,说明RFC结果如何成为制度化的。例如,如果RFC建议为团队规范一个技术观点,那么一旦RFC获得通过,这个观点应该被纳入到你的工程指南和入职文档中,以便于对当前和未来员工都是规范的。

  1. 将速度作为目标,而不是策略

在《好策略/坏策略》一书中,作者理查德·鲁梅尔特将好策略定义为提供三个要素的策略:对如何克服挑战的诊断、指导政策或总体方法,以及执行政策的一系列行动。策略是旅程的规划。

相比之下,目标是对一个目的地的描述。我听到过无数个团队告诉我他们的策略是追求速度,但没有说明如何实现这个目标。我完全同意工程速度和快速是一个很好的目标,但这不是一个策略。

下面是一个提供高速工程交付的示例策略:

挑战:我们是一家非受监管的初创企业,需要在资金耗尽之前尽快迭代以找到产品市场适应性。

诊断:我们有机会最小化复杂性并快速行动。由于我们尚未找到产品市场适应性,迄今为止我们构建的价值非常有限,因此我们需要忽略已投入成本,选择快速重写,因为我们仍然不确定未来产品的样子。

行动计划:我们将专注于招聘软件工程综合型人才,加强对好奇心和机智的文化的培养,把自我放在一边,只在长期技术规划方面投入适度的工作量。相反,现在我们将专注于我们将MVP产品实验交付到市场的能力。

  1. 参与持续教育和技术会议

如今,技术会议随处可见,几乎每个软件工程的细分领域都有一个志同道合的聚会。如果你的团队还没有要求过预算参加这些会议,他们很可能会在某个时候提出要求。一个典型的预算请求可能是1000美元用于机票和住宿费,500-1000美元用于入场费和膳宿费。总之,一名工程师参加会议的费用大约为2000美元,外加上班时间的损失。出于学习和持续改进的初衷,以及一系列附带的好处,我建议你预算并定期批准或系统地批准会议请求。

即使员工仅仅因为参加会议而对相关技术主题有所了解,这样的成本也是值得的。然而,还有许多其他好处。

我建议你要求会议参与者在返回后撰写一份总结他们所学到的关键内容的文件。你还应考虑赞助与你的业务最相关的会议,并让你或你的团队成员主持关于特定主题的研讨会。这些研讨会和赞助提供了卓越的品牌推广机会,让你的公司的名字和信息出现在一个非常有针对性的观众面前,这个观众很可能包括你将来想招聘的候选人。

总之,为工程师们安排会议预算对于个人的专业发展非常有益,而且只需要进行一次较低工作量的文档记录。这对于团队的学习也是有益的,并且是一个通过网络、赞助或主持招募团队未来成员的好机会。

  1. 使用橡皮鸭调试法

你有没有遇到过这样的经历,在解决一个问题时,当向同事解释问题时,突然找到了解决办法?橡皮鸭调试法是一种简单的实践方法,试图在不需要同事介入或切换上下文的情况下复制这个现象。

橡皮鸭调试法的过程是首先将问题大声说出来,并且可能对着桌上的一只真实的橡皮鸭。这个想法是通过大声说出问题,通常人们会听到问题的缺陷,或者在问题只存在于大脑中时,会看到解决办法。橡皮鸭调试方法可以节省同事的打断时间,并更快地得到答案。

  1. 建立一个解释视频库

如果一张图片抵得上一千个字,那么一个声音解释一个技术话题的一分钟视频,伴随着桌面/IDE/应用程序的展示,价值相当于节省了1,000美元的开发人员时间。有许多工具可以轻松地录制和共享这些迷你视频消息,包括内置于Slack和Loom中的工具。通过屏幕录制和配音,你可以更容易地清楚地传达技术想法,而无需文本,而且你可以在自己的时间内完成。结果视频可以根据观众的选择加快速度,视频可以存档,并作为组织知识库的一部分随时重新观看。

作为团队的技术负责人,我鼓励你定期制作这些迷你视频解释,特别是在对平台架构进行更改时。在内部wiki中将所有视频以库的形式组织起来。确保它们完整而独立,但简短而有重点;如果你在过长的视频中直到最后才介绍关键内容,你的团队成员可能永远不会看到它。此外,尽可能使方法保持一致,以便观众知道可以期望什么。

我保证,前期你的视频观看率可能不太理想,但随着时间的推移,这个库将作为参考知识的宝库,节省你和你的团队大量的时间。

  1. 入职是每个人的责任

你的团队不断地创造部落知识,无论是如何启动一个服务,还是如何在代码库中使用代码模式。处理这个问题有两种方法:你可以无所事事,每天增加新员工的知识差距,或者你可以积极努力,将孤立的部落知识转化为可以为当前和未来员工提供可伸缩文档的知识库。出于显而易见的原因,我推荐后者。这意味着每个人都应该时刻问自己,“我该如何记录我刚刚创建/学到/发现的内容?”当你遇到新员工遇到他们在知识库中找不到的内容时,他们就需要寻找答案并记录下来。

技术债务

旧金山的金门大桥是由钢铁构成的,实际上并不是金色的。桥梁被涂漆,保持其标志性的颜色对旧金山人来说非常重要,他们不断地刷新油漆(参考链接http://ctohb.com/painting)。这种持续的投资或永续维护是保持最重要和复杂的系统符合预期性能要求的要求,无论是金门大桥还是你的团队的软件项目。只是对于你的项目,维护不需要涂漆桶,而是以技术债务的形式出现。

软件开发团队交付的每个功能都伴随着未来工作的一定程度的需求,即债务。这些债务可能采取修复错误、为特性提供增量的客户价值或修复代码中的疏忽,以改善可维护性、性能或安全性的形式。即使你的团队在度假期间,一定程度的债务也会自然而然地积累:出现在依赖软件中的安全漏洞,软件包过时,工具的新版本发布,第三方API被废弃或更改,等等。债务是不可避免的,你需要考虑它。

技术债务和产品生命周期

另一种理解技术债务的方式类似于金融债务,比如房屋贷款。当你为购买房屋而贷款时,你会做出有意识的决定去承担债务,并知晓债务带来的后果(利息),以便你能立刻得到自己想要的东西(拥有房屋)。然后你会在较长时间内持续偿还这笔债务(月供)。

技术债务也是如此。你的创业公司可能会有意地积累技术债务作为一种有意识的权衡,并且在这个权衡中制定一个现实的还债计划。对待技术债务,你应该像处理金融债务一样,要么一次性偿还,因为你有多余的资源(而且没有更好的用处),要么持续地分期偿还,或者在将来一次性偿还,但可能会以更高的总价包括利息。

无论你选择如何偿还技术债务,成功的关键在于认识到债务是软件工程过程中不可避免的一部分,并且主动偿还债务是对整体工程健康的必要投资。

定义技术债务

另一种理解技术债务的方法是将其视为一种技术决策、实现或细微之处,对当前或未来的业务效率或效果产生消极影响。关键是技术债务有重要的后果。你的代码可能是客观上丑陋或低效的,但如果这种低效对业务没有影响,并且未来不需要修改那段代码以保持质量、性能或迭代,那么这段代码在技术债务方面是低成本的。毕竟,软件开发的目标,特别是在初创企业中,不是编写完美的代码库,而是构建能够支持业务的软件。

不要害怕债务。它可以起到一定的作用。例如,在构建尚未在市场上验证的产品的第一个版本时,技术团队可能会决定采用无法扩展到百个用户以上的架构。如果这个决策可以让团队迅速验证产品是否能够吸引百个用户,那么这条道路可能是值得的,特别是考虑到可能需要多个原型版本才能找到受用户喜爱的版本。

技术债务至少有七种类型:

  1. 架构债务设计债务,当软件的设计无法满足业务的近期或未来需求时产生。例如,设计使得构建业务需要的功能过于困难,或设计无法满足业务的用户数量或性能要求的扩展。
  2. 代码债务是在没有关注最佳实践的情况下进行实现,导致难以理解和维护的代码。
  3. 测试债务是因为你运行的自动化测试不足,无法给团队提供对代码库正确性的信心。
  4. 基础设施债务发生在基础设施、监控和支持系统没有足够的强大或维护不良,导致难以扩展或部署更新,或者导致可用性和可靠性低下。
  5. 文档债务是由于文档不足或文档过时/不准确,这可能导致团队成员难以接触项目。
  6. 技能债务在团队成员缺乏维护或更新代码或周围基础设施所需的技能时出现。
  7. 过程债务是当团队在解决问题的方式上不一致时产生的,导致错误、延误或增加成本。

技术债务破产

如果你的初创公司长时间忽视或忽视技术债务,它可能成为未来进展的重大障碍。由于技术债务,团队可能无意识地发现自己花费了80甚至100%的时间来处理系统问题或低效率的情况,这种情况被称为技术债务破产。

以下是你的团队可能处于技术债务破产状态的一些迹象:

  • 你经常遇到生产故障,对业务产生实质性的影响。
  • 处理债务需求常常收到阻力或夸大的时间线。
  • 团队抱怨代码库太复杂,无法有效工作。
  • 新功能无法交付,容易在不经意间破坏旧功能或引入不可接受的高级别缺陷。

如果发现自己处于技术债务破产的状态中,现在是时候发出警报,与各方重新设定期望,制定一个解决技术债务的计划,并立即开始偿还债务。

如果你在与同行领导进行了诚实的沟通(参见《传递坏消息》第46页),你应该具备说明技术债务问题并发展共同理解技术债务投资回报率的必要信誉。

衡量债务:债务清单

与抵押贷款或汽车贷款不同,没有一个网站可以给你一个关于你的技术债务金额和剩余偿还的明确数字。一些形式的债务可以进行定量衡量,但大多数分析是定性的。为了健康和负责任的大规模债务管理,我建议进行一次债务清单调查。

此调查应按照固定间隔进行。每年进行一到四次,对各种债务进行冷静分析,以便诚实评估团队目前的运作状态。调查不应由单独进行,而是与每天在代码中工作并定期接触债务的其他工程师一起合作进行。

调查可以简单地是这样的:对于以下类型的债务,评估我们拥有多少,使用1到10的等级进行评分,然后提供几句话来证明评分。

利用调查结果来决定团队如何消耗精力偿还债务,并比较随时间进行的调查结果,以确保债务保持在合理水平,你的团队定期解决其最大债务痛点。

偿还债务的策略

为了决定何时偿还技术债务,你首先应考虑你的团队的时间值多少。关键考虑因素包括:

  • 根据最新的债务清单调查结果,有多少债务存在
  • 债务对公司日常运营的影响程度,例如,通过故障、客户流失或缺陷率
  • 债务对团队实施新项目的能力产生的影响

支付债务的难度如果您没有陷入技术债务破产,并且您的目标是保持健康的债务水平,我建议将团队的10-20%的时间用于非功能工程投资(例如,偿还债务、探索新的模式/概念验证、改善开发者体验等)。您当前债务影响越严重,偿还债务的努力越大,您应该分配给团队的时间比例就越高。

及时偿付

处理技术债务最常见的方式是按照即时付款的方式偿还债务,这意味着债务将作为业务驱动项目的一部分进行偿还。通常情况下,团队在计划会议中会添加与此次迭代选择的故事相关的技术债务任务。这种方法的优点是低开销、计划工作量较小,可以很好地运作。但请注意以下一些潜在陷阱:

  • 由于及时偿还的方式对整个团队来说不够明显,可能导致对技术债务的系统性低投入。确保在付款期限到期之前对团队进行诚实和透明的沟通,说明您预计团队在偿还债务方面占据的总时间百分比。
  • 在迭代中作为一部分添加技术债务可能暗示着投资技术债务次于迭代目标的次要目标,因此有可能在时间不足时将其从范围中剔除。
  • 在迭代中解决技术债务可能被视为减慢迭代进程或导致延迟,而不是作为提高速度和整体系统健康的一项投资。
周期偿还

周期偿还类似于偿还汽车贷款或抵押贷款的方式。团队在固定的时间间隔(例如,每个迭代一天、每月几天或每个季度几周)里留出时间来偿还债务。谷歌曾经让他们的工程师拥有百分之二十的时间做他们想做的事情,包括偿还债务、开展创新项目和工具等。这里的想法是一样的:作为经理,您明确地制定时间,并鼓励团队对用于工程的工具和流程进行投资。

例如,Shape Up方法(请参阅Tech Process第157页)描述了一个六周周期之后的两周冷却期,或八周周期的百分之二十五,用于进行技术投资。请记住,25%并不是一个魔法数字;正确的百分比将取决于您团队的债务清单。

持续偿还

根据您的团队的债务负担有多大,您可能需要投入更多的资源来提高整体系统质量,而周期策略不足以实现这一目标。这看起来像是一支专门的团队,我称之为客户组,在双组(见项目维护:双组理念,第113页)场景中支付技术债务作为他们日常工作和目标的一部分。

重要的是确保任何主要目标是内部效率的团队,例如技术债务团队或客户组,对其工作有明确而可衡量的目标。例如,如果您的债务清单将测试债务列为最高债务类别,则测量缺陷率和代码覆盖率,并要求客户组负责改善这些指标。如果您的基础设施债务最大,则关注正常运行时间和平均恢复时间等指标。

技术债务的沟通

非技术领导者并不期望技术团队做到完美。但他们期待高绩效并保持持续满足期望。

在债务方面,这意味着清楚地沟通您保持债务在可控范围内的策略,以及提前和坦诚地沟通债务可能妨碍业务目标的时间,并说明偿还债务的策略。

技术路线图

时间范围

我发现将技术路线图划分为三个时间范围非常有用,有时被标记为短期、中期和长期,或者第一、第二和第三个视野。每个时间范围应由不同的过程管理,并且通常由不同的利益相关者拥有。

短期/第一视野

您的短期路线图是您的团队当前正在处理的事情。这包括任何正在进行中的功能、主动修复的缺陷、技术债务或紧急工作项。有关管理短期路线图的详细信息,请参见“Tech Process”部分的“工作流程”(第157页)。

中期/第二视野

如果您是团队中唯一的技术经理,则您负责中期和长期路线图。如果您有向您汇报的董事或高级经理,则您可能会在中期路线图上进行合作。中期路线图是非常有用的工具,不仅可以用于您自己的规划和组织,还可以用作与其他部门/利益相关者沟通工程团队正在做什么的工具。

通常,中期路线图以电子表格形式实施,其中团队或个人作为行,列是时间段,通常是按周或迭代划分,表格的内容是高级别的工作项或工作领域。路线图的目的不是精确预测任何给定任务何时完成;这样做需要准确和精确的工作估计,这在最好的情况下是脆弱的(甚至以周为单位的粒度)并且永远不能保证。相反,该想法是概述操作顺序并为团队设定一个方向。

您可以并且应该在工程进展的过程中更新任何给定活动的实际持续时间。在给定任务上更新周数是评估是否继续投资项目是否有意义的良好时机,也可以将当前完成估计更新给外部利益相关者。最后,该路线图有助于回顾跨度重大举措所花费的时间,并评估团队在一个非常高的层面上投入时间的情况。

长期/第三视野

作为团队的领导者,您需要关注团队的长期健康和生产力。您应该花时间设计这些目标,并制定一个经过深思熟虑的、清晰的文件(或幻灯片、视频、维基文章等),以向团队说明这些目标。设置初始目标后,随着战略目标的变化会导致组织动荡,您应该定期进行更新。同样令人担忧的是,频繁的方向变动可能会让团队感到困惑和沮丧。我鼓励您每个季度向整个工程团队以及其他高级领导人提供关于长期倡议进展的更新。

一些长期倡议的例子:

架构技术债务

  • 从已弃用的框架迁移到正在维护的框架
  • 从一个托管环境迁移到另一个托管环境(例如,使用Kubernetes)

语言债务

  • 整合编程语言的使用
  • 从旧版本的语言迁移到新版本(如从Python 2迁移到3,或者从.NET 4迁移到.NET 5+)

平台/架构采用

  • 多个团队采用或迁移到内部服务的新版本
  • 迁移到/从无服务器环境
  • 采用新的范例(如服务器端渲染、边缘计算)

招聘计划

  • 扩大或重新组织团队
  • 招聘专家或建立新的技术部门

时间线沟通

我与销售、市场营销、产品或支持方面的领导者合作过,他们对技术流程和技术路线图的透明度表示感激。相比之下,我曾与某些公司的领导人交谈过,他们将其技术团队描述为一个黑洞。不言而喻,您不希望被称为黑洞。不成为黑洞很简单,就是指您的组织中有一个定期提供透明度给其他领导层的流程。理想情况下,您还可以通过拥有一个论坛或机制来收集意见,并将其纳入路线图流程中,使其他部门感到被听见。您还可以回应相关方的请求,并向他们沟通其请求在开发流程中的进度,并管理好他们对其完成时间的期望。

工程流程

康威定律认为,设计系统的组织机构受到组织的沟通结构的限制,即组织如何构建团队以及团队之间和内部的工作流程将对您的产品产生重大影响。在信息孤岛中工作的团队不太可能生产出与其他团队设计完美融合的产品,因此,作为监督者和这些沟通结构的最终架构师,您需要确保这些结构满足您正在开发的产品的需求。

工作流

技术工作是一个高度细微的问题,会对最终的互操作和行为产生影响。为了在组织内保持生产力,您需要一套规范和指导原则,以确保日常的技术决策在广泛一致的前提下,对团队是可管理的。这意味着您需要真正建立这些标准、对团队进行培训,并拥有一个日常流程来强制执行和修改这些标准(如有必要)。

团队遵循以确定构建什么和如何完成工作的方式被称为工作流程。最流行的五种工作流程模式是:

  • 敏捷
  • SCRUM
  • 看板
  • 瀑布
  • Shape Up

有关这些模式的整本书都被写过了,而我最喜欢的是《Scrum: The Art of Doing Twice the Work in Half the Time》(《敏捷开发 Scrum 指南》) ,作者是杰夫·萨瑟兰。

这些方法的一些基本优势和缺点将在本章中进行讨论;然而,在现实世界中,过程之间的差异相比于经理对所选择的过程的良好实施的影响要小得多。作为技术领导者,你的工作是选择一个过程,并确保它被很好地实施和迭代。

一个好的开发过程应该尊重以下有关软件开发的真理:

  • 没有人能够完美地预测完成任何特定工程任务需要多长时间。
  • 工程很少是一条直线;构建特性 X 可能需要在能够构建 X 之前花时间解决问题 Y。
  • 没有所谓的完美规格说明;在构建技术的过程中总会存在空缺和待发现的事物。

通常,工作流程的目标是确保团队有良好的组织并以可接受的速度交付。某些工作流程甚至试图以迂回的方式量化工程团队的速度,从而向非技术利益相关者报告速度随时间的变化情况。

瀑布模型

最古老的工作流程之一可以追溯到上世纪50年代,就是瀑布模型(参见 ctohb.com/waterfall)。瀑布模型将项目活动分解为顺序步骤,每个步骤都依赖于前一步骤完成后才开始。在软件工程中,它看起来像首先有产品愿景,然后进行产品构思,接下来是产品设计,然后软件开发,最后是测试、部署和维护。瀑布模型最常见的批评是该结构过于僵硬、不灵活,并且不支持迭代开发。

敏捷/Scrum

敏捷和Scrum方法比瀑布模型更加微妙和具体。有许多优秀的资源详细介绍了这些细微差别,包括萨瑟兰的Scrum,Mike Cohn的《敏捷估算与计划》(《敏捷估算和计划》) ,James Shore和Shane Warders的《敏捷开发之道》。

关键的是要意识到这些过程只是指导方针,而不是教条。要使您的工程团队发挥最佳作用,首先选择一个工作流程,然后看看它在您特定的人员和技术挑战与需求下的成效如何。有些团队的工作更适合进行估算和故事点估算,而其他团队的环境更加复杂,估算几乎是不可能的。注意任何流程中是否有任何仪式真正为工程团队带来价值,或者它只是一场每个人都讨厌的冗长会议。

不要犹豫跳过对团队来说不明显有益的工作仪式。例如,我发现 SCRUM 对规划扑克的规定大多数团队来说效率低下。

Shape Up

Shape Up 是由 Basecamp 公司正式制定的一种方法,该公司出版了一本名为《Shape Up》的电子书,可在 basecamp.com/shapeup 上获取。Shape Up 的核心周期为六个星期,比 SCRUM 倡导的短期周期要长得多。这个周期使用了固定时间和可变范围。这个想法是较长的时间周期为产生清晰的提案(说明书)提供了更多空间,并对项目进行良好的工作。相比于其他模型,Shape Up 对估算的重视较低,这是对工程团队来说是一件好事,很快我将讨论为什么是这样。

工程估算

根据谷歌的说法,精确度在技术上的定义是测量、计算或规范的结果与正确值或标准值的一致程度。也就是说,准确性是整体正确性的指标。当您在飞镖靶上投掷飞镖并瞄准靶心时,准确的投掷是一组投掷趋向于中心的投掷。

相比之下,精确性在技术上被定义为测量、计算或规范中的精炼程度,特别是通过给出的数字来表示。换句话说,精确度指示了一个精确程度。当投掷飞镖时,如果您的所有投掷无论目标在哪里都紧密地聚集在一起,就可以说这是一个精确的分组。

正如这个描述所帮助您可视化的那样,某样东西可以准确但不精确(在靶心周围或靠近靶心的一片范围内选择了一组飞镖),可以精确而不准确(一个紧密聚集的飞镖组,但没有命中靶心),当然还有可能既准确又精确(一个紧密聚集的飞镖组,也命中了靶心)。

您应该期望并追求您的团队对软件开发任务的准确性,但不一定是精确的估算。如果今天是一个月的第一天,您的团队提供的合理指导是“我们将在本月内推出该功能”。如果团队说“我们将在23日推出该功能”,他们更有可能无法满足这个期限。

如果您按周、月或季度来计划工作/资源分配,那么不需要尝试估算每个工单的小时数或天数。随着时间的推移,注意您的估算是否真正为您希望的计划能力提供了帮助。如果没有,请不要惩罚团队并继续这个流程,更不要把它作为绩效评估的一个因素。相反,调整估算使其对您有所帮助,而不是伤害您。改变您的期望,不要仅仅因为错过估算而做出反应,而是因为团队在努力满足估算时面临的挑战。

最后,关于估算的一点说明:不要将估算错误视为总体输出/速度不佳。有些团队效能非常高,产出很大,但仍然会错过估算。速度是更重要的指标,而高效但估算不准确的团队不应受到惩罚。相反,经常错过估算而且难以交付新的有效价值的团队则表现不佳,需要做出改变。

燃尽图

SCRUM 燃尽图显示了团队根据估算的进展情况,并可以是衡量冲刺生产力的重要工具。然而,由于估算的不完善以及其他原因,燃尽图可能呈现为水平线或甚至上升线。这可能是因为团队确实没有取得进展,或者可能是估算问题或数据收集不良的结果。

燃尽图会持续上升,即使团队在运送工作和做出良好成绩,也会令人沮丧,并未取得预期的效益。如果有简单的调整可以帮助你更好地收集数据和修复燃尽图,那就做这个改变。但是,如果你发现某种测量输出的特定方式仍然不起作用,那就放弃它。承认你对估算这些特定类型的问题的方法不够精确,并转而采用其他监控和提高绩效的方法是可以的。

根据我的经验,在使用燃尽图的团队中,只有很少一部分团队能够取得成功,所以如果这种技术对你的工程团队没有帮助,不要感到气馁。

选择工作流

我认为你选择的工作流程对你的工程团队的最终成功和速度不会是一个重要因素。关键因素是你是否关注你的团队的工作流程,并不断迭代工作流程本身,以确保你的模式增加价值并与你的团队和团队面临的问题类型匹配。

话虽如此,下面是一个大致的模型来思考哪种工作流程可能是一个更好的起点:具有良好理解的工作(即具体、新颖且易于解释的任务)更容易管理,并且通过更细致或规范的计划过程可以产生更多的好处。换句话说,如果你的工作模糊不清且难以估算,那么使用看板(Kanban)可能更好,而不是SCRUM。

适合SCRUM的明确理解的故事包括:

  • 全新的代码,不依赖于可能是旧的或难以处理的外部模块
  • 不依赖于新的模式/工具/技术,而是依靠现有(乏味)的技术堆栈
  • 可以将故事分解为更小的任务,团队对之前的工作很熟悉

相反,如果你的工作是:

  • 需要处理现有技术债务并且清楚的付款/重构路径不明确
  • 经常变化或受到不可预测的优先级的限制
  • 需要采用新的和不同的工具和模式,可能会在最初的几个实现中引入意外成本
  • 指派给一个全新的团队,他们没有一起工作的历史或者没有处理过这类项目的经验

冷却/创新冲刺

当使用固定的节奏(如冲刺)时,团队很容易陷入的一个主要危险是期望冲刺结束后,功能将会交付,并且团队可以立即转向下一组功能。由于债务的累积和对产品功能的迭代需求,这是不可能持续的。必须要有连续的或定期的时间用于支付债务。

一种常见的定期支付债务的做法是冷却冲刺。有时称为技术债务冲刺或创新冲刺,其思想是给团队时间来整理他们的数字工作空间,做一些代码整理,以确保他们和代码都处于良好状态,以便将来可以高效工作。正如《支付债务策略》的第150页所讨论的那样,合理的做法是将总开发时间的5-20%分配给冷却工作。

如果你每两周进行一次冲刺,这意味着每四到五个冲刺中有一个专门用于冷却。

技术规划与规范

在与工程师讨论撰写技术规范的过程中,我经常被问到:“你怎么有时间写规范?”通常我会反问:“你怎么没有时间写技术规范?”我隐含的回答是,在开始构建之前花时间思考你要构建的东西是一个节省时间的方法。

软件工程本质上是一个创造性的过程,这意味着我们不是每次都做相同的事情,每个故事都有多种解决方法。一个很好的规划过程认识到事先思考故事的价值,但也要平衡这种强调前期规划的知识,真正了解一个特定功能的所有细节的唯一真正方法是实际构建它。

一个优秀的技术规划过程可以实现几个目标:

  • 减少功能中的重新工作量
  • 找到更少的工作量来实现相同的功能
  • 减少遗漏重要的非业务可见考虑因素的机会,例如错误处理/负面情况、测试、日志记录、监控、分析、安全性、可扩展性、发布计划和技术债务偿还
  • 增加多个人/团队的工作以兼容方式进行
  • 为以后维护、改进或扩展一个功能提供有价值的文档,以解释为什么以某种特定方式构建了一个功能
  • 保持团队对不可逆/昂贵技术考虑(例如工具和架构)的思考和对不太可能遗忘的关键细节的一致性
  • 证明足够轻量级,以便在合理的时间内完成,并且不会在不重要的细节上强制进行决策,这些细节要么无关紧要,要么没有足够的初始信息

技术规范负责人

我建议为需要规划的任何项目指定一个负责人:一个人负责制定技术规范并将其通过批准流程。

这并不意味着他们是唯一的贡献者。相反,如果在规划窗口期间其他团队成员可用并具有帮助的知识,他们可以并且应该做出贡献。

规划可以是同步的(即每个人在整个时间段内都在一个房间里)或异步的。我推荐尽可能进行异步规划,因为规划工作中的大部分工作将涉及研究(例如阅读产品文档、阅读代码、原型/概念验证、评估工具和API等),这些工作可以独立完成。

规划时间

你的技术规划过程应该在最初的实现中节省时间。通过最小化技术债务并留下可以加速将来改进的文档,它还可以节省将来的时间。

投入规划的时间不当无法实现这些目标,因为时间太短,无法节省时间/产生良好的文档,或者时间太长,无法在节省时间上回报。

没有确定的正确时间的通用公式,但我会提供一个经验法则:为每周工作估计的项目技术规划分配一天的时间。通常,这将导致计划窗口在半天和三天之间。如果你的项目需要少于两天的工作时间,那么它可能需要很少的计划工作量并且风险较低。相反,如果你要处理一个预计需要三个完整开发周期以上的项目,你可能无法一次性有效地规划这么大的项目,并且应该考虑拆分。

如果你的团队拒绝投入时间进行规划,那么你可能过分强调结果而忽略了过程。确保工程流程为业务带来良好结果的方法不是更加用力地逼迫,而是建立一个健康的过程,使其能够实现良好的结果。你不会让一支设计桥梁的结构工程团队加班来加快速度。你会确保他们拥有最好的桥梁设计工具,并且对被桥梁所跨越的跨度有尽可能多的信息。软件工程也是如此。但是,我们没有CAD软件或土壤/岩石的真实世界测量数据,我们有的是产品说明书、设计过程和软件工具。

相反,团队成员坚持事先获得每个细节的过长规划流程可能表明存在严重的文化问题,团队成员因为害怕犯错误而瘫痪。有效规划无法消除风险,但是提前思考重要的高层决策可以将其最小化。过度关注细节的团队可能害怕犯错误或不愿意对工作进行迭代,这两种情况都是过分结果导向管理的症状。不应该因合理的错误或规划疏漏而惩罚个人。技术规范不完美是可以接受的;希望团队在实施过程中发现问题或空白,并在发现这些问题时更新规范。

规范编写中的原型!

在撰写技术规范时,你可能会发现有多种选项可以实现某个目标,但没有明显的理由支持一种或另一种方法。或者你可能会发现关于特定选项的有效性的未知因素,从而使决策变得模棱两可。如果可能(特别是如果可以高效地完成),我鼓励你给你的工程团队留出空间来构建一个或多个解决方案的原型,以获得数据,以便在规划过程中做出更好的决策。花半天时间创建一个新工具的玩具原型,以验证这个工具是否可以事先达到期望结果的可行性是值得的。

技术规范内容

拥有一个团队在开始撰写技术规范时使用的模板是加快速度和确保不遗漏重要主题的好方法。我建议你的模板主要是一系列具有要涵盖的主题领域的标题,或许还包括一些针对技术规范作者的指导或提醒的内容。我在ctohb.com/templates中包含了一个示例技术规范。

在开始讨论内容之前,有一个小插曲:技术文件可能会有点枯燥和严肃。如果符合您的企业文化,我鼓励您在适当的时候注入轻松愉快的氛围,以增添趣味性而不会分散注意力。一个好的例子是在文件顶部放上一个巧妙的网络迷因,与规范主题相关。根据我的经验,只要有一个经理/领导在规范中制作了一个迷因,他人就会(理解:打开闸门)参与其中。

可包括在模板中的一些建议的组件:

  • 提醒文档实际上是一个模板,并鼓励作者在开始撰写之前先复制一份(这种错误很容易犯!)
  • 关于如何思考规范的指导/参考公司规范指南和批准流程
  • 解释项目的商业原因的背景部分
  • 此项目具有的任何特别突出的技术风险领域(例如,涉及敏感个人身份信息,或涉及以前未使用的工具/架构)
  • 对任何非明显术语的术语表/定义
  • 规范旨在实现的任何明确的业务目标/与先前确定的目标的相关性(即,季度KPI或OKR)
  • 解决方案架构概述(文档的主要内容)
  • 技术债务明确讨论为什么或为什么不需要处理任何必需/相关债务
  • 数据建模,包括对数据库或数据流的必需更新
  • 内部和外部报告或分析和测量要求
  • 测试
  • 部署
  • 功能切换/标志
  • 对整个系统可靠性或灾难恢复的影响
  • 安全性和隐私
  • 可交付的里程碑

技术规范批准

为了确保在项目和团队成员之间实现一致性和对齐,你必须确保团队成员阅读和为彼此的规划过程贡献。我的建议是,在规格书被认为是完整之前,为规格书设定一个轻量级的审批流程。

审查目标

你的技术规范审查目标应包括以下内容:

  • 确保所有团队/项目在技术方向上保持一致,并进行一致构建。
  • 审查并教育团队重要的数据概念/技术合同。
  • 确保对手头问题有普遍且一致的理解。
  • 最小化遗漏重要边缘案例或其他非业务可见需求的机会。

审查过程

我对轻量级审查过程的建议是在文档中进行异步对话,随后进行同步冲突解决会议(有关冲突解决会议的更多信息,请参见《会议和时间管理》,第28页)。一旦技术规范的作者在项目的关键要素上取得了一些进展,就应该将文件分发给具有足够上下文的其他工程师。其目的是让其他人读文件,并在自己的时间内留下评论和问题。其中许多问题可以由技术规范主要作者迅速解决,但有些问题可能是有争议的或高度微妙的,需要更高带宽的沟通。

在完成该过程时,作者应安排一次会议,参会者只有那些已经阅读文件并提前做出贡献的人。会议的目的是审查待解决的问题和冲突,并达成解决方案。会议的目的不是让作者简单地向一个无趣或不感兴趣的听众朗读规范。如果有悬而未决的问题需要进一步深入研究,以了解并解决这些问题,那么请在会议之外完成这些工作,并与仅感兴趣的团队讨论结果。

一旦解决了所有悬而未决的问题,记录参与撰写规范的人(以便将来的读者知道应该向谁提出进一步的问题),并考虑文件已获批准。

技术规范审查会议中的领导者

技术领导者或经理并不需要成为所有技术文档的批准者。我建议你建立一种文化,团队整体上对贡献安全感并且不依赖于你来提供技术的靠山或支持。在早期,部门相对较小的时候,你应该在大多数或所有规范中都进行深度参与,但这种方法无法扩展。一旦您雇佣了其他高级个人贡献者、架构师或经理,授权他们成为主要审查者,并听从他们的意见,让他们做他们雇佣来做的工作。如果你发现高级成员在这些评论中没有很好地指导团队,不要在公开的论坛上抨击他们。请私下讨论并进行必要的调整。

技术规范作为文档

你的技术团队现在正在花时间创建深思熟虑的文档,涵盖了你如何工程化你的产品,而团队作为结果产生的错误会越来越少。技术规范帮助你的最后一种方式是为将来需要增强或修改已完成工作的工程师提供有用的资源。我建议你创建一个组织良好且可搜索的目录(例如内部wiki,如Confluence或Notion,或Google Drive之类的文档存储),并确保你的团队勤奋地将所有规范文档添加到目录中。将规范链接或引用到代码注释中以解释为什么要实现某些功能的方式也可能会有所帮助。

开发人员体验(DX)

DevOps工具公司Harness(harness.io)将开发人员体验(DX)定义为开发人员在工作向目标迈进时所感受到的整体互动和情感。它类似于用户体验(UX)的定义,只不过在这种情况下,主要用户是软件工程师。

开发者体验并非总是通过仪表板来衡量,但当设计不佳时,团队能够感知并且可能大声抱怨。糟糕的开发者体验可能会让工程师在整个下午都陷入困境,例如,尝试启动微服务进行测试时出现了一条晦涩的回溯,而服务的维护者正在度假,因此中级工程师耗费了数小时的时间试图建立可靠的构建-执行-测试循环。

将这种效率低下乘以团队中的所有工程师以及公司中存在的各种类型的存储库、服务和项目,这可能很快导致直接时间损失的人月产能。加上为解决问题而引进其他人所花费的额外上下文切换时间,糟糕的开发者体验很快就会成为一个需要重视的问题,如果不加以解决,它可能会破坏一个本来高效的工程团队。

有两个前提条件可以带来良好的开发者体验:

  1. 工具能够轻松创建高度可靠和可复制的环境和依赖链
  2. 对操作的文档和规范的一致性

值得庆幸的是,如今有很多可用的工具和生态系统可以帮助实现上述要求。大多数编程语言都有一个标准化的工具生态系统用于依赖管理和可复制环境。您需要识别并使用这些工具(如npm、pipfile等)。其中许多系统会生成一个称为锁定文件的文件。

锁定文件不是用来避免死锁的并发管理工具,而是用来锁定依赖关系图的特定实例。您应该提交这些锁定文件,并确保其他开发人员和任何构建系统都使用它们。锁定文件有助于确保团队中的每个人都安装了相同的依赖关系集合。

如果您选择的编程语言没有提供这些工具,则您需要通过使用Docker容器、Makefile或其他方式来构建可复制性。

通常情况下,良好的开发者体验(DX)和糟糕的开发者体验之间的区别在于耗费有经验的代码库人员二三十分钟的前期努力。

确保基本构建命令在新安装中起作用,并在本地README中文档化这些命令,并为您作为CTO提供了一个使这种工作更容易的机会,即确保在您公司的所有存储库和代码库中使用的构建命令是一致的。也许每次都是docker-compose up或者总是yarn run。无论是哪种情况,任何开发人员应该能够克隆任何存储库,然后首先想到的构建和运行软件的命令就能够工作。

优先考虑开发者体验

在产品路线图之外的任何事物都可能很难确定优先级。

幸运的是,开发者体验很少需要投入大量时间进行路线图调整。在公司初创阶段,我更喜欢遵循童子军规则,即把代码库(或开发者体验)搞得比您刚入职时好。每当开发人员遇到构建、运行或测试问题时,都应该是他们的责任来修复、记录或确保下一个阅读该代码的人对此更容易。

随着系统的规模变大,将所有内容在本地一起运行以测试功能可能成为一项越来越繁重的工作。在这一点上,可能值得在路线图上更正式地投资开发者体验,甚至是专门的人力资源,以确保工具正常工作,开发人员不会浪费大量时间与系统作斗争而不是编写有生产力的代码。

简单的开发者体验宝库

下面是一些快速优化软件工程团队开发者体验的建议:

  • 编写一个包含运行代码库的说明的README文件,最好是一个一行命令安装依赖项、构建和运行代码。
  • 强制所有代码都要按照在公司的所有使用该语言的地方一致的严格代码样式进行校验。如果代码样式不通过,构建应该失败。如果所有开发人员都配置了自动代码样式检查的IDE,构建因代码样式问题而失败的情况应该很少出现。
  • 尽可能地将代码样式配置文件放入源代码控制中(例如通过设置类似于VSCode的settings.json文件来投资,地址为ctohb.com/vscode)。
  • 投资时间来确保可以从零开始在本地数据库中设置本地测试数据。通常,快速生成数据或种子数据脚本可以解决许多开发人员的头疼问题。最好是,如果种子数据可以很容易地增加以添加额外的边缘情况/使用情况,使基础测试数据集尽可能全面/具有代表性。
  • 制定一项计划,以便在需要时模拟或实际创建依赖服务以测试多服务交互。理想情况下,在良好的契约和面向领域设计的情况下,这种需求会很少出现,尽管在必要时应该很容易实现。

为开发者体验更换工具

2022年,独角兽金融科技公司Stripe决定将其当前的编程语言Flow更换为成本过高。Flow使用了太多内存,导致笔记本电脑卡顿,并且与开发者IDE集成得不好。

TypeScript与Flow类似,都是构建在JavaScript之上的可选类型语言。TypeScript的采用范围比Flow广泛得多,因此解决了Stripe团队与Flow遇到的许多问题,而这些问题随着时间的推移变得越来越困难。很明显,与Flow相比,TypeScript在开发者体验方面提供了重大改进。唯一的问题是,如何将数百万行代码从一种语言转换为另一种语言?

答案是,一个由工程团队组成的18个月的项目,为了准备一个单一的大型合并提交,更新整个代码库。2022年3月6日星期日,Stripe的超级合并提交完成,3月7日星期一,团队回到工作中并开始使用新的编程语言。一位开发者将这种改变描述为他们在Stripe期间最大的开发人员生产力提升。

这告诉我们,如果糟糕的开发者体验给人们带来足够严重的痛苦,那么几乎没有任何成本是太高或者无法改进的项目。您的团队几乎肯定比Stripe的规模小,并且您可能不处理数百万行代码,但是同样的原则也适用于您:如果团队在开发者体验中遇到麻烦,需要投入必要的时间和精力来改进以获取效率。

团队经常面临的另一个问题是过频繁更换工具。在某些技术生态系统(尤其是JavaScript领域),似乎每个月都有新的发展,这可能会为团队提供提高生产效率的新工具。我鼓励您在采用新工具时要果断,确保您已经花时间真正理解了现有的痛点,审查了新工具,并评估其是否符合您的所有要求,而不仅仅是它的吸引人标题,然后再做出决策。有关我在这方面推荐的流程的更多信息,请参阅Implementing Internal Technology Radar,第204页。

本文是 THE STARTUP CTO’S HANDBOOK 中译版,由极客智坊翻译服务自动翻译完成,另有中文PDF版本提供下载:创业公司CTO手册。:

微信扫描体验极客翻译

One Comment

发表回复