成年人按时交付软件的方式
让我们先简单介绍一下这篇文章的背景。首先,我是一家网络代理机构的首席技术官,负责处理许多短期项目,通常只有一两名开发人员参与。我也参与过一些涉及数十名开发人员的多年期项目,但这只是我经验中很小的一部分。
这里我们所说的客户,指的是那些你花钱、你托付希望的人。他们可能是你初创公司的创始人,但对我来说,他们就是字面意义上的客户。
最后,我讨厌所有技术项目管理和方法论的胡言乱语,所以不要指望我使用复杂的术语,也不要部署使火箭发动机看起来很简单的公司方法论图表。
这里的目标是让您了解我对软件规划的看法,从您必须给出估算的时间到产品的准时交付。
估算
可以合理地假设,绝大多数开发人员不喜欢做估算。正如#NoEstimates运动所言,在项目开始前,想要在10分钟内精准地估算所有项目绝对不可能,但客户的资金有限,而且他们希望在3个月后参加一个活动来展示他们的产品。你或许无法承诺所有事情,但你绝对必须承诺一些事情。“准备就绪”的理念是业余爱好者和老掉牙的“大佬”们最乐于接受的,而我们这些有责任心的成年人则必须提供估算。
注意——这需要估算人员和公司项目都具备丰富的经验。个人经验能够提供准确的估算并发现所有隐患,而 Git 历史记录或之前的时间表则可以用数据支持这些数字。如果您经验不足,需要意识到这一点并寻求比您资深的人员的帮助,否则您将陷入困境。如果您不知道,那就不知道,没关系!
变得粗暴
通常我第一次需要估算的时候,是商务团队来找我做新项目的时候。规格或多或少比较详细,但你得自己处理。
主要思路是创建工作分解结构的初始版本。你可以使用思维导图工具,例如Coggle,或者直接用一张纸。列出程序的所有不同模块(例如“前端”、“后台”、“API”、“移动应用”等)。然后列出每个组件的所有功能。如果某个功能跨越多个模块,则将其分别放在每个模块中。
然后看看你的树,想想你是不是忘了什么。有很多常见的步骤,比如登录/注销页面、密码恢复、邮箱修改流程、各种邮件、GDPR cookie 同意、分析跟踪等等。
然后看看你的树,问问自己你忘记了什么。也许是你需要的额外的隐形障碍,也许是一些会扰乱你计划的规定,也许是未表达的隐性客户需求,等等。
然后看看你的树,问问自己忘记了什么。直到你的想法枯竭。
然后看看你的树并问自己忘记了什么。
不过请放心,您可以得到一个粗略的估算,从而确定一个切实可行的截止日期。在这方面,我总是喜欢参考阿波罗计划——该计划除了开发软件本身之外,还发明了软件工程。肯尼迪总统在“我们选择登月”的演讲中公开宣布了这一截止日期,此前他的顾问们研究了各种可以在截止日期前完成的太空技术方案。这花费了巨额资金吗?是的。它成功了吗?也是的。我们稍后会讨论这个问题。
评估您的风险
正如Tim Lister在《风险管理是成年人的项目管理》中所解释的那样,风险管理是项目管理尤其是软件项目管理的基础。
在项目的这个阶段,您必须确定两件事:
- 该项目存在的理由的核心特征
- 最危险的功能,其时机难以确定,可能是因为你缺乏这些特定任务的经验
有趣的是,事实证明,风险最高的功能通常都是核心功能。这很合理,因为这正是这个项目与其他项目的不同之处。
这个风险很大的部分值得你全神贯注。试着向专家咨询,让他们帮你估算这些任务。看看有哪些库或框架可以帮助你完成这项工作。阅读博客文章,并寻找 Stack Overflow 上那些令人绝望的评论。
有了这些知识,你大概就能估算出接下来任务的规模了。然后准备一些缓冲液,让它再多做两遍,再准备一些缓冲液,让它再打磨一段时间。
请注意,如果您遇到一些有风险的部分,而这些部分恰好远离价值主张的核心,那么您真的应该协商将这些部分移出范围,或者至少限制对它们的承诺。
注意——如果你的项目包含研发,那么问题就完全不同了。研究无法保证结果和时间。你的项目可以实现源自学术研究的功能,但千万不要把赌注押在尚未发现的东西上。
估算常规任务
现在是时候估算业务中风险较低的部分了。对于你树中的每个小项目,想想它需要多少天。别害羞,所有事情都需要很长时间。我最初几年经常犯这个错误,估计有些任务只需要几个小时甚至几分钟,因为我觉得更长的时间会让人觉得荒谬。这并不荒谬,你需要时间才能正常工作。这就是为什么我以天为单位估算所有事情,很少需要超过半天。
然后,你就可以开始你的树了,并为每个节点计算每个叶子节点的计划工作量之和。可以随意将总和的一小部分加到叶子节点上。假设你设想了这样的场景(为了演示,略微夸张了一下):
- 我的项目 (8)
- 登录 (4)
- 表格(1)
- 密码恢复(2.5)
- 形状 (0.5)
- 电子邮件 (1)
- 密码修改(0.5)
- 注册 (3)
- 表格(1)
- 电子邮件确认 (1)
- 电子邮件确认页面 (0.5)
- 登录 (4)
如你所见,该项目耗时 8 天,但如果只看叶子节点,总计耗时 5.5 天。随着层级的上升,耗时会加长 2.5 天,这说明项目的复杂性不断增加,处理其他部分的难度也随之增加。这受到了COCOMO模型指数因子的启发。
协商最后期限
很多时候,客户——或者你之前的商业团队——不会对给出的价格和/或截止日期感到满意。在这种情况下,你必须记住,你做出这些估算是有原因的,而且没有办法降低它们。
提前完成截止日期的一个办法就是加班。这绝对不是你能坚持下去的,但如果项目只有几周时间,那么晚点回家,周末加班或许能帮上忙。缺点是你会精疲力竭,需要一段时间恢复。我以前也这样做过,我知道在这种冲刺之后,我至少会整整一周都无力回天。
您也可以投入更多人员,但这需要巧妙地进行,以便每个人都可以完成自己的任务,而不会受到其他团队成员进步的阻碍。
然而,你拥有的主要工具是缩减范围。如果你想提前完成项目,那么你唯一真正的筹码就是缩减范围。所以,你可以从树上开始修剪树枝。可以是零星的几片叶子,也可以是粗大的树枝。通常,你可以从许多花哨但用处不大的需求中精简项目。
不要忘记四肢
根据项目规模,这一点或多或少会有所体现,但你当然需要关注项目的设置和部署。大多数情况下,我建议以功能为导向,但对于这两个方面来说,这是无法压缩的技术任务。
设置将包括创建代码仓库、创建项目脚手架以及运行一些基本功能。本质上,它是配置您将在项目中使用的框架。
部署是指对开发和生产平台的配置,有时在您常用的基础架构中很容易完成,但有时需要根据客户的要求进行,因此不应忽视。如果客户的IT流程复杂,并且要求您通过特殊的VPN进行部署,而该VPN在月相进入特定阶段时每次只能运行10分钟,那么您最好考虑一下这一点,并将其纳入预算中。
规划
仇恨之路的下一站是规划。不过,如果你一直遵循这个方法论,你会发现它相当简单。理论上,本节更适合项目经理而非开发人员,但实际上,每个人都应该知道发生了什么以及为什么会发生。
基本结构
虽然在大型项目中,你可以开始并行化工作,但最好尽可能地让任务按顺序进行。当你开始做某件事时,确保前一个任务已经完成。我建议的大型任务顺序如下:
- 功能规范。使用Axure之类的原型设计工具。然后将其转化为功能单。在我的公司,项目经理就是做这件事的。
- 平面设计。请不要使用 Photoshop,作为一名开发者,我更喜欢看到Sketch 的设计。团队使用Avocode来沟通设计,这使得设计集成时能够达到非常高的精度。这也不是开发者的工作,因为这是图形设计师的工作。
- 技术规范。它不必是一份冗长的正式文件,但至少要与技术主管坐在一起,决定主要的技术选择(通常是前端和后端框架)以及解决项目风险部分的策略。
- 开发。在这里,您可以做自己喜欢的敏捷事情,弹出自己喜欢的工具并编写漂亮的代码✨。
- 数据填充。如果项目需要数据,那么一旦特征存在,就可以开始填充数据,但在此之前不能开始。
- 测试。虽然每天都会针对每个功能进行测试,但在发布之前,将在整个平台上进行大量测试,这将导致一轮错误修复。
- 发布。这意味着将代码推送到生产平台。这需要尽早进行。如果可以,请将测试和发布颠倒过来,以便在测试过程开始之前就首次将代码发布到生产平台。
审查规格
项目经理将规格说明书交给您后,您需要仔细审核。您之前所做的初步估算就是您的预算,现在您需要确保最终的规格说明书与预算相符。
所以,从估算中取出你的WBS,并根据最终规格进行更新。这次你应该对要生产的产品有一个相当准确的了解。
问题在于,当规范写得不好,边缘情况被遗忘时,问题就来了。务必仔细研究规范,从各个角度考虑,确保其合理且所有情况都得到考虑。否则,你会在开发过程中发现问题,那就太可惜了。
审查规范的另一个重要部分是指出哪些功能需要花费过多的时间,却几乎没有任何附加值。用户体验设计师和项目经理并不总是了解程序的底层工作原理,他们可能会毫无理由地选择非常低效的解决方案。开发人员的职责就是避开这些陷阱,转而推广简单的解决方案。
— XKCD,任务展示了计算机科学的能力是多么违反直觉
注意——很容易遗漏一些东西。你不知道自己不知道什么。遗漏的东西不会凭空出现在你的脑海里。你需要建立一个思维过程来帮助你突出那些遗漏的东西。这是另一篇文章的主题,但一些想法包括用不同的角色广泛测试线框图,开始构建数据模型或创建序列图以确保一切都符合要求。
数据填充
一个重要方面是确保所有数据都有来源。在设计过程中,很容易出现混乱,到处都包含大量文本和图片,但每一点信息都必须考虑周全。此时,数据的来源必须清晰明确,并且数据最终进入数据库的方式也必须纳入规范。
您可能需要一个后台系统来填充所有数据。在这种情况下,您还需要考虑如何实现后台系统,并将其包含在您需要投入的时间中。我通常使用Django 管理网站或Wagtail来生成这些界面,因为它们非常高效,我非常喜欢它们💕。
您也可能会从 CSV 文件或外部 API 注入数据。在这种情况下,您需要确保您的数据源能够以您可利用的格式提供所需的数据。
无论如何,在应用程序的数据模型完成之前,你都不能开始填充数据。如果你在数据模型准备好之前就开始填充电子表格文件,以“争取时间”,那么我告诉你,你肯定会做错事。在找到一个标准的数据填充方法之前,不要开始填充数据。
订购开发
假设您的类似 Spotify 的应用程序有 3 个主要分支,其中两个核心功能以粗体显示。
- 用户管理
- 登录
- 登出
- 忘记密码
- 配置文件管理
- 音乐
- 浏览目录
- 搜索
- 奏乐
- 计费
- 信用卡管理
- 收据下载
您按照什么顺序制作它们?
您可以从技术上将其拆分,然后说您创建了一个音乐引擎、一个音乐目录、一个计费引擎,然后在所有这些之上添加一个 GUI。
您还可以按照功能的绝对重要性顺序来执行操作,因此从计费开始,然后是音乐和用户管理。
但是,如果你延误了进度,又必须立即发布项目,那该怎么办呢?最重要的是,如果你想测试一下你所做的工作,会发生什么?在这两种情况下,功能都不是独立的。如果你的客户无法先找到音乐,就无法测试音乐播放。
在你的规划中,要把最重要的事情放在首位,把重要的模块放出来。在这种情况下,播放音乐并向用户计费。然后你需要确保你能够触及这些模块。所以在开始音乐播放之前,你需要用户能够导航到音乐。在此之前,你需要他们能够登录。但是,你实际上并不需要他们能够更改密码或填写个人资料。
假设这款应用存在的目的是为了付费,但人们使用它的真正原因是因为它可以播放音乐。此外,你也可以在不提供付费功能的情况下发布它,因为你的商业政策很可能包含免费试用期。
考虑到所有这些,我会按以下顺序规划功能:
- 登录
- 浏览目录
- 奏乐
- 搜索
- 登出
- 忘记密码
- 配置文件管理
- 信用卡管理
- 收据下载
这样,从第 3 步开始,你就能始终开发出可用的产品。虽然不完整,但绝对可用。当然,核心功能之一被推迟到了最后,但这是出于业务考虑而做出的明智决定。
发展
现在我们已经到了本文的最后一部分。如何才能在截止日期前完成软件开发?
遵守规范
让我们用一段话来强调一下规范的重要性。如果规范不够精确,或者在项目过程中发生变化,以下建议将变得非常难以遵循。中途更改规范的主要原因(即使不是唯一原因)是为了缩小范围,如下所述。糟糕的规范会使项目时间增加一倍或两倍,即使是最资深、经验最丰富的开发人员也一样。
一次做一件事
因为我是John Wick 项目管理的忠实粉丝,所以让我们回顾一下 John Wick 3 开头这段视频中发生的事情:
正如你所见,约翰·威克被一群想要置他于死地的恶棍追赶。他走进一个房间,发现了几把老式手枪。他可以做很多事情,但他没有慌乱,而是花了一些时间打造一把完美的手枪,专门用于这次射击。然后他杀死了另一个人。他时间紧迫,获得了MVP称号,并且活了下来。
本文最有用的建议是,在进行下一个任务之前,务必完成全部任务。你不能留下任何未完成的事情。你的代码中不能有TODO注释。你不能留下任何积压的东西等待修复。一旦你的思绪飘忽不定,就会忘记一些事情,而这些积压的东西会永远积压下去。
当然,这是否可行很大程度上取决于你对任务的选择。你需要确保你的任务规模小且可实现。它们要密封严密,不会与其他任务混杂在一起。有时这很困难,有时相互依赖会使任务规模变得很大,但我从未遇到过我脑子里想不起来的任务。
最终,当截止日期变得紧迫,或者仅仅是因为公司流程过于粗略时,就会有人发疯,要求你同时做两个不同的任务。你必须忽略它,坚持一次只做一项任务。如果你心存疑虑,不妨想想:如果有人同时在各个方向奔波,那么他们会忘记你要求的一切,因为他们根本记不住自己胡言乱语。这样,你就可以按照自己的决定去做,他们也不会因此责怪你。
这样做的另一个副作用是,你不应该编写现在不需要的代码。你编写的所有代码都专注于实现当前功能,而未来的功能根本不重要。也许你可以牢记这些功能,以避免搬起石头砸自己的脚,并引导一些决策,但绝对不要为未来的功能编写任何代码。这样做会分散你的注意力,让你感到困惑。这些未来的功能甚至可能在你实现之前就发生了变化。
我推荐的技巧在某种程度上受到了番茄工作法的启发,但它并非基于时间。相反,你应该为当前步骤设定一个目标,并且在完成之前不要偏离目标。完成后,稍事休息,然后继续下一步。
测试测试测试
我不会提任何关于自动/手动测试的建议,但有一件事是肯定的:你需要彻底测试你的软件。用所有不该用的方式测试它。
任何你发现的故障都应该引起你的警惕。尝试重现该故障,并查看代码,看看会发生什么。根据我的个人经验,90% 的“奇怪故障”最终都会变成生产环境中令人恼火的 bug。
此外,您需要让客户或至少一些项目经理每天测试您的代码。
- 尽早发现 bug,可以确保你有一个健康的工作基础。bug 越多,就越难发现一个!
- 通过让项目经理测试您的工作,您可以确保遵守规范,从而不会陷入长达数周的误导之中。
真实数据
我们在上一节中看到,只有当有标准方法可以填充数据时,才必须填充数据。反之亦然:永远不要用模拟数据进行测试。必须使用尽可能真实、数量尽可能大的数据进行测试。
如果可能的话,甚至可以使用比生产预期更大的数据集进行测试,以确保它适合。
使用真实数据与上文提到的 bug 相关。如果你一直只使用同一组数据,就很容易出现 bug。
不要绊倒
在软件开发中,还有一件非常容易发生的事情,就是莫名其妙地遇到一些技术难题,然后无缘无故地浪费掉几天时间。这种情况会在你不知不觉中悄然发生,耗费你大量的时间。
避免这种情况的最好方法是定期回顾你的工作,并退一步思考。你可以和同事、项目经理、老板一起做,但每周至少要回顾几次,看看自己在做什么,看看自己是否遇到了瓶颈。
另一个技巧是,当你知道自己可能会因为正在做新事情而陷入困境时,最好给自己的工作设定一个时间限制。这又一次给了你机会,在为时已晚之前纠正轨迹。
如果你陷入困境,那么也许你可以改变方法,寻求帮助,休息一天来清醒头脑,或者做任何你认为合适的事情,但你肯定必须做点什么。
处理延期项目
项目管理三角是项目管理中一个众所周知的概念。它与我上面写的内容很契合。
正如我们之前在阿波罗计划中看到的,他们设定了目标范围、最终期限和最低质量要求(也就是不杀死宇航员)。最终花费巨资的原因在于,这是他们为了满足条件而必须做出的唯一调整因素。这也是为什么NASA最近的重返月球计划肯定无法按时完成的原因,因为美国纳税人可能还没准备好支持一个吞噬金钱的怪物。
成本增加
为延迟的软件项目增加人力资源会使项目延迟
尽管上面引用了布鲁克定律,但你可以为延期的项目添加资源,但必须非常小心。有两点需要注意:
- 这会增加项目成本,所以总得有人为此买单。可能是你的客户,可能是你的公司,也可能是共同责任,这些都不是开发商真正关心的。重要的是成本的增加。
- 这会拖慢现有团队的进度,因为需要沟通的人越多,就意味着更多时间没法投入到编码工作中。因此,如果要这样做,你必须有一个已经适当松耦合的项目,并让新开发人员负责那些与现有部分交互不多的远程部分。你希望新增的劳动力能够弥补生产力损失。
增加成本是一种选择,但必须谨慎使用。很多情况下,尤其是在项目规模较小的情况下,这样做是行不通的。
增加时间
推迟最后期限似乎是一个直观的选择,但实际上在这样做之前有很多问题需要考虑。
- 客户准备好接受延期的项目了吗?
- 您的公司是否有足够的精力来投入到这个项目上?
- 考虑到您要做的不是有偿工作,而是免费工作,这会花费您公司的钱。
- 拖延项目对团队士气非常不利,尤其是当项目进度比最初估计的超出 50% 以上时。
就像成本增加一样,时间的增加也有一些弊端,包括成本本身的增加。这真的不是我们想看到的。
缩小范围
好消息是,正如上面所说,你已经按顺序逐一完成了所有操作。这意味着每次提交都是一个成品。也许并非所有提交都经过了同等程度的测试,但至少目标是确保每次提交都是一个成品。
这意味着你现在就可以把产品投入生产,不用担心零件出问题。一切都很顺利。
这确实大幅缩减了项目范围,但这并非你唯一的优势。的确,在规范制定过程中,有些内容是以特定方式指定的,但如果你结合项目当前的经验和开发人员的视角来思考,或许可以找到一些捷径,虽然会稍微影响用户体验,但能确保按时完成。
简而言之,当你迟到时,你有两种选择:
- 在发布日期时,根据当前的开发进度来缩减范围。这些功能或许稍后会完成,也或许不会。这取决于商业谈判。
- 简化剩余的功能,使它们可能不太方便用户使用,但可以更快地完成。
换个说法。你和客户签署的文件上写的是截止日期、价格和项目范围。这意味着,只要你的项目完成了它应该做的事情,按照约定的价格,并在规定的截止日期之前完成,那么规格细节就是项目中最具可协商性的部分。
考虑到这一点,当你的项目延期时,你应该找到一种方法来缩小范围,因为这是迄今为止最不痛苦的跨越终点线的方法。
结论
虽然估算和规划是复杂的任务,但完成它们也是我们工作的一部分。事实上,如果我们自称是软件工程师,我们就应该能够承担与其他类型工程师同等的责任。如果一座桥能够按时建成,那么软件也应该能够在截止日期前交付。
首先在项目开始时进行粗略估算,然后随着规范和代码的生成缩小计划,同时确保预算和截止日期与实际完成的工作一致。
我们在项目的不同阶段看到的一种模式是,如果你想更快地交付你的项目,你可以使用不同的调整变量,但最安全和最有效的肯定是在范围上发挥作用。
最重要的教训是仔细安排你的任务并逐一完成它们,这样你就可以控制工作的复杂性并使你的项目保持健康的状态。
归根结底,我们的开发人员工作往往更像是落地页,而不是机器人和激光。我看到很多初级员工对这种前景感到失望,也看到很多资深员工只想进入管理层。然而,我们这个行业充斥着项目超出预期的情况。既然我们的工作如此轻松,那就至少努力按时交付吧。
致谢
以下文章是我创作本文的灵感和校对来源。其中很多内容我并非 100% 赞同,但它们也确实值得一读。
- 时间估计的权衡— Beekums 教授
- 关于如何应对截止日期和估算— Eddy Ernesto del Valle Pino
- 开发人员项目管理 101 — Yaakov Ellis
- 如何转向#noestimates — defmyfunc
- 这需要多长时间?Git 知道。—— Dimitrios Melidonis
- #NoEstimates 的方法— Jay Bazuzi
- 我们如何利用改进套路将生产力提高 25% — Philippe Bourgau
- 关于评估事物— 特里·布朗
- 企业范围的软件估算第 1 部分和第 2 部分— Vitalie Temnenco
- 风险管理是成人的项目管理——蒂姆·利斯特
- 为什么软件项目耗时比你想象的要长——一个统计模型——Erik Bernhardsson
- 极限编程——简单介绍— Don Wells