十一月下旬,技术团队接到产品运营团队的一项需求迭代:在月底的重大运营活动前,技术团队需要将 App 内所有页面,添加将页面分享到内部社区的新功能,并且需要对分享图片功能进行改造升级,添加二维码并支持 App 内跳转功能。
我司的开发流程是采用迭代式增量的敏捷开发,本次的需求迭代,是一个完整敏捷冲刺周期,也是一个完整的项目周期,还是一个聚合类业务类项目的典型推动流程,期间的设计和经验,也可以为被类似的业务类项目参考。
时间紧:目标上线时间已经明确,盘点一下,除去留给用户的版本更新时间,从规划到上线,只有八天时间。
范围广:这一需求,对于一个成熟且业务单元相当复杂的 APP 而言,牵扯到全部页面,近 20 个业务单元,累计近 80 个功能点。且功能涉及后端、前端、客户端协作,而且需要和部分独立运作的业务单元团队进行协作。
该项目的典型特点是:改造时间紧张,需求涉及范围广,技术难度中等,项目管理难度大。
目标明确后,我们就要着手规划行动方案了。先讲一个经典的人类首次征服南极点的故事。1911 年 12 月前,没有人类到达过南极点。1911 年 10 月,有两个探险家团队,几乎同时从南极圈外围基地出发,去争夺人类首次征服南极点这一荣誉,其中,一个是阿蒙森团队,另一个是斯科特团队。结果,阿蒙森团队率先完成目标,并于 1912 年 1 月 25 日全部返回基地,他们作为人类历史上第一个到达南极点的团队被载入史册。而斯科特团队不仅落后一个月到达南极点,而且所有成员在返程中全部丧生,是什么造成了二者截然不同的结局呢?
阿蒙森在分享探险经验时说:“最重要的因素是探险的准备如何,你必须要预见可能出现的困难,遇到了该如何处理或者如何避免。然后,按照计划执行。”
正如阿蒙森的经验一样,实现一个目标的先决条件是做好规划。分享迭代项目的目标是按时完成所需的功能,这一目标明确后,我们开始紧罗密布地做规划。
首先,要与各业务单元密切沟通并对它们做详尽的调研。永远记住,细节是魔鬼,前期的细节调研投入是值得的。正如上文提到的征服南极点的故事里,在出发去南极点前,阿蒙森和因纽特人一起生活了一年,来调研如何在冰天雪地里生存。阿蒙森团队考量了爱斯基摩犬和矮种马等运输工具的优缺点,调研了极地环境滑雪的困难,调研了如何才能更好的保暖,等等,前期的详尽调研,是阿蒙森团队成功乃至存活下来的决定性因素。
其次,依据调研,结合可利用的要素,制定详尽的实施操作规划。阿蒙森团队依据调研决定选择采用更加耐寒的爱斯基摩犬拉雪橇,选择了爱斯基摩人的皮大衣。还发挥创造性,特制了雪地靴,改良了雪橇,选择新路线,以及每天前进 30 公里的计划,使得其最终返回的日期和原定日期一天不差。作为反例,斯科特团队采用的矮种马,都被冻死在半路,机械摩托也中途坏掉,最后只能靠人力拉雪橇。软件研发项目的规划的过程中,范围、时间、质量、人力、架构、管理,都是管理者可以结合的要素,其中前四个是较为经典的项目管理四要素。在本次分享迭代项目中,范围、时间、质量要求都非常清晰,架构设计、管理措施、人力协调,是本次项目迭代重点规划的内容,这也是大多数业务类敏捷项目的迭代惯例。
最后,拉上干系人对规划进行审查。审查不但可以对规划过程进行监督,还广泛吸收经验。阿蒙森在冲刺南极点前也广泛吸取经验,不但咨询了曾在北冰洋漂流过的南森的意见,甚至团队使用的前进号探险船,也是南森推荐并转交的。我们的分享迭代项目在技术评审阶段,也发生将设计架构推导重来的过程,但从最终效果来看,前期规划过程是是必要的,也是非常值得的。
规划永远是代价最少、影响最大的工作。往往投入较多的精力为一次工作做规划,那做这项工作所用的时间就会减少。在时间如此紧迫的情况下,我们也花费了也将近 2 天左右(1 天并行)的时间来进行前期规划。
我司当前敏捷开发的架构规划阶段,实际上融合了需求分析、概要设计、详细设计的阶段。
分享在业务发展过程中一直未进行统一的规划,随着业务的发展,代码在不断堆砌,虽然局部范围需求并未有太大影响,但一旦涉及增加站内分享的全场景需求时,诸多问题就暴露出来:
第一,客户端和前端分享页面各自为政,请求各自业务单元获取分享所需数据。存在多种实现方式、请求数据格式也完全不统一。
第二,虽然后端对客户端分享请求做了一定的统一,但是统一也只是做到了对接口聚拢的层面,由分享汇总接口,去主动适配各条业务线。这就导致后端的汇总接口里,将近 20 个 switch case 分支,还在有不断递增之势。新增的业务场景分享时候,汇总接口要去适配业务场景,客户端需要发版。
第三,当前的汇总接口也远未覆盖本次新增的需求。
需求分析的过程,要利用好抽象的武器。抽象可以把复杂的事情简单化,通过简单的本质来覆盖未来的场景。在架构设计之前,应当尽可能的对需求进行抽象,我们将分享的业务场景抽象为三类,站内、站外、图片,它们每一类的特点明确。其中,站内(朋友圈、微信)和站外(社区、消息)的特点是,面积比较小,产品发挥的空间有限,需求稳定,它只能容纳四五个字段,如方图、标题、简介。图片面积较大,产品发挥的空间较大,可以容纳较多的字段,和另外两类分享有明显差异。本次新增需求,即是新增了站内分享,外加图片有调整改动。
架构设计以抽象的需求为基础,经过抽象,我们认为将各业务单元的分享,有通过依赖倒置被统一为分享服务的必要,这一服务,也有能力来覆盖未来的场景。
项目初期,该需求由产品层,直接指派给客户端团队,因为从产品团队角度看,客户端团队是最接近该需求的表象改动。
第一轮方案由客户端团队主导设计。客户端团队计划在现有后端汇总接口的基础上进行适配,来支持站内分享。这轮指派和方案,符合被动推动工作的惯性思维,即代码发生在最接近需求的地方。虽然这最符合直观逻辑,但属于在现状基础上继续堆砌,现存的问题会继续恶化。纯客户端进行适配,仍然要与各业务线单元进行联调,而且,系统里存在大量未被收拢的分享页面,需要客户端自行去对接,或者依靠汇总接口去适配。由于这些问题在技术评审阶段被提出,我们紧急展开了第二轮的整体设计。
第二轮方案中,架构采用依赖倒置的方式实现。后端创建分享服务,它统一对客户端、前端的所有分享页面、统一提供数据,各业务单元的后端适配分享服务。同时,对于图片生成,各业务线自行提供图片生成模板,并基于通用字段产出分享图片。第二轮依赖倒置方案的第一个优势是,保证分享服务、图片服务、分享组件无需再进行改动即可支持新增业务,完全符合开闭原则,系统内保持更多的不变模块,对修改关闭、对扩展开放。
第二轮设计方案的另外一个优势是,它分散了项目管理风险。第一轮方案会将所有风险集中在客户端和各个业务单元对接上。而第二轮方案可以在保持客户端、后端组件稳定不变的同时,将集中的工作,合理的分散至各个业务线的客户端和后端。
从代码重构的角度看,我们意识到这是推动架构重构的绝佳时机。
首先,重构的影响范围和工作量,与在现状基础上进行堆砌需求的工作量相差不大。
其次,重构后,有利于推动眼前需求的完成,更有利于未来需求的完成。依托需求迭代,进行机会性重构,是改良代码的重要时机。一个需求最终完成的成本,不仅在于开发代码,还有前期梳理沟通、测试等成本,而机会性重构,则可以有效复用这些成本。与第一轮方案相比,第二轮方案的团队整体工作量并未减少,但第一轮方案会让整体架构变得“更为腐烂”和难以维护。
此外,我们在结合本次业务需求时,还直接加入一系列相关技术驱动的优化:
从项目的角度来看,它们扩大了改动的范围,但是从系统而言,是否也增加了分享迭代需求的研发成本?未必,系统之美在于系统有内在奇妙的联系,将系统内部结构调整的更趋于合理后,不但未增加整个系统需求的工作量,在从系统上降低开发风险同时,也提高了整个系统的可维护性和可扩展性。
从项目管理的角度看,架构设计如果把复杂的事情都压在单个节点上,风险可能更高,而经过良好解耦设计后,每个人只做简单的事情,即便增加参与人数,系统风险仍然会降低。因为简单的事情可替代性强,容易进行风险应对,且分散后的局部发生风险不会引发全局风险。第二轮方案将原来客户端的单点,分散至后端和客户端各业务单元,虽然参与人数增加,但是整个项目系统风险极大降低,也是本次分享需求时间极端条件下,还可以顺利迭代成功的前提。架构之美不仅在软件的可维护性上有所体现,好的架构设计会有利于项目管理的推进,降低全局成本。
项目管理角色承担着统筹项目推进的责任,而不少技术公司或团队,并没有专门的项目管理角色,其通常由对项目有一定熟悉的技术人员承担,这样虽然缺乏较为专业的项目管理技巧,但是也有一定的优势,如项目管理角色可以参与到架构设计中。我们建议项目管理者也参与到架构设计中,这样有利于识别项目关键风险点,并引导采用降低项目管理成本的设计。通常情况下,架构之美是全方位的,有利于项目管理的设计和优秀的架构设计不冲突。
项目开始执行前,项目负责人要确保争取到的足够的资源和条件,使得当前团队对项目目标 “跳一跳,够得着”。依据架构设计,分享迭代项目,需要充足的并行业务单元开发人员、关键节点攻坚的技术骨干、业务单元管理人员,都不可或缺。一定要注意,和资源严重不匹配的目标是不切实际的目标,会让人倍感挫折。团队一定是渴望胜利的,奋力跳一跳而完成的目标,是非常吸引人的,即便过程困难,但成功的喜悦会补偿过程的艰辛。
由于项目的范围、时间、质量明确,那就要争取人力资源。极端的项目要求,需要较多的人力资源来支撑。分享迭代项目,也首先粗略估计出所需要的人力资源,以及协调后对其他项目影响,如下面表格。沟通过程中,罗列清晰的客观细节,给予对方明确的预期,不但能体现项目管理者的专业性,还可以提高信任度从而达成较好的结果。
依赖这一评估和沟通,我们还从管理层争取到了非常有利的条件:如果分享项目需求的人力资源影响其他项目,那么以分享项目为高优先级。在和管理层协商时候,我们强调,虽分享迭代项目虽然牵扯大量的人员,但大部分属于局部参与,受影响的时间仅为 1~2 天,对产品整体进度影响较小,所以这一要求还是相对容易被满足的。这一条件的争取对于我们并行推进业务单元开发非常有利,可以作为我们与争取资源的底牌。
即便尽力争取资源,也并非总能事如所愿,如客户端团队,由于自身规模较小,抽调人员既要参与核心节点又要参与并行业务单元开发,压力十分巨大。和客户端负责人沟通后增加人手,但仍然捉襟见肘,只能依赖赶工来抵消一定资源风险。
虽然项目是临时团队,但团队管理的设计直接影响计划的执行效果,也至关重要。 依据上文阐述的关键节点,我们设计了纵向负责人和横向负责人协同推动的制度:横向负责人,管理并推动业务单元完成目标;纵向负责人、作为技术对接人,管理关键技术节点对接。纵向负责人和横向负责人相互支持,共同推动工作网状铺开:
纵向和横向的协同需要有工具来支持,不要小瞧工具的力量,工具其实是经验的具象化。我们这里使用简单的责任进度矩阵表格来推进工作,它和我们的横向纵向负责人设置也相互呼应。如下图,表格内每个格子标注 Done 就代表该任务单元格完成。大范围、高强度的短期攻坚项目中,工具越简洁明了越有优势。这一矩阵也将具体责任明确到人,避免了因责任分散而产生旁观者效应。该矩阵也可以看做将时间维度简化为固定值的甘特图,并融合了责任分配矩阵的含义(向经典工具靠齐)。
下面便是我们实际开发中的表格截图,整个开发过程中,虽然项目需求和 BUG 仍然用 Jira 来管理,但对外沟通和开发阶段管理,我们使用了该表格:
资源协调和团队设计完成后,我们需要开始制定详细的进度计划。在这一阶段要规划出里程碑,和各个节点的启动和完成时间。依据系统设计,我们首先识别出关键节点:后端分享服务完成、客户端分享组件完成、站内分享后跳转完成、站内分享数据更新框架完成。然后,再识别出关键路径,如下图,其中标红色的是关键技术节点,标记为绿色的是可以并行推进的并行节点,绿色节点是多个业务单元汇总,每个业务单元逻辑简单。红色关键节点完成后,绿色节点由各个业务单元来进行并行推进。
依据关键路径和关键节点,我们的里程碑设置如下:
依据里程碑二、三内存在核心节点一对多联调对接的特点,我们在这两个里程碑内,分别安排了两次集中联调,集中联调的优势是:可以快速的解决沟通和拖延问题,但仍然要注意节省团队时间,我们采用了枢纽人物驻场,其他相关人员联调一波走一波的方式。
整个项目,由于涉及细节较多,考虑到测试和未知风险,我们将开发时间压缩在三天,留四天时间给测试。整个执行过程进度十分紧张,每天都是一个里程碑的推进,和团队管理相结合,里程碑一更依赖横向负责人推进,里程碑三更依赖纵向负责人推进。有些项目管理者,喜欢计划外仍留有一定的 buffer。但依笔者所见,既然定下目标,就要想尽办法完成。要尽可能保证对内对外沟通一致,避免出现”狼来了”的故事。如果目标未达成,要么是计划未做到位,要么是执行过程未到位,做计划并达成计划应当是项目管理者的基本素养。
任何一本项目管理书,都会提到项目启动会的重要性。不论日常项目大小,我们都建议有个正式的启动会,且尽可能当面沟通,人最容易接受的习惯是面对面的沟通,还能传达情绪和意志,作出规划及承诺。我们的项目启动会也不例外,分享项目也在动工前,召开了启动会,旨在达成以下目标:
除以上务实的目标外,项目启动会也应当是一场重要的战前精神动员,精神的力量不容小觑,精神动员不但可以提高士气,提高团队成员的积极性,同时还能减轻执行过程中潜在的激烈冲突等问题:
团队奔向目标的过程中,需要持续被鼓励,在项目推进期间也要跟上精神动员。如测试后期也要给大家铺垫:“前期,大家耗费了大量的心血,距离胜利只有一步之遥,这波攻坚战后,就是最后的胜利。“
前期项目规划的越详细,后期阶段越容易执行。如果要问执行期间最重要的经验是什么,那仍然是做好规划,做好规划,做好规划。
抛开规划而言,执行阶段的成功,很大程度也是对人管理的成功。短期项目执行期间,绩效等工具都发挥不了直接的效应。所以使用设计好集中联调,里程碑节点、上下游督促等手段更为有效。而且,把握执行阶段性的主要矛盾,也有利于把项目监控和管理资源倾斜在关键点。分享项目开发执行过程中的各阶段矛盾如下:
整个执行过程中,我们采用敏捷开发措施中常用的每日早晚站会对执行过程进行监督。站会耗时短,但能高效透明执行过程中的信息,及时暴露执行进度是否偏离规划,并对进度吃紧的关键路径赶工。
细节是魔鬼。由于项目具有唯一性和渐进明细的特性,虽然尽最大可能的进行调研,并确保做有详细计划,但风险仍然会出现。在计划里要完全覆盖所有细节,这不太可能,但认真做过的计划则能覆盖大部分的致命问题。
项目执行过程会逐渐暴露各种细节问题,我们要能保持冷静的心态和敏锐的洞察力,并积极应对。比如大范围做改造需求时候,一定会出现不符合设计标准的地方,遗留的万年不变得到各种代码,可能又会被翻出来,就像分享开发的过程中,遇到有的项目 id 使用 string,有的地方使用 int 类型,有的地方使用加密 ID;有的角落地方,有新老类型不统一的问题;客户端 H5/RN 实现方案不统一,等等。对于这些风险,我们采取两种措施来处理、回避和应对。
有些决策是很难做出来的,特别是面对改造时间和风险的压力角逐时,要首先想到的是最理想的方案是什么,即使现实条件无法达成,也可以去寻找尽可能向理想状态靠拢的折中方案。
如需要对统计埋点中商品的新老类型进行兼容,客户端和后端都可以进行兼容,那就采用后端兼容,以尽快后续版本下掉兼容代码。技术人应当有技术人的理想,理想状态原则不止是理想,也是技术设计最实际的利益诉求。
要确保决策会有利于项目范围的收敛。比如项目管理者要确保一旦进入开发阶段,所有需求就进入收敛阶段,非致命的变更需求,可以移至后续迭代,这也是敏捷迭代式需求开发天然支持的属性。需求的蔓延,不但会影响全局的计划,而且会打击研发的士气。这就像打仗,好容易看到山头插红旗了,又冒出来一撮敌军,还不知是不是陷阱。
同时,要确保决策会有利于不良设计的收敛。要确保决策有利于不良设计收敛,将无法及时改造的不良设计收敛在局部,避免扩散,不仅可以减少维护成本,而且能减少后期优化改造的成本。
通过规划和执行阶段,所有需求及问题,此刻都一一解决了。那就一丝不苟的准备份上线清单吧!”清单“ 是另一个简单而强大的工具,是公认的避免犯错误的最有效工具。我们通过将对仿真环境的上线的演练,收集为一份上线清单,有效降低了复杂项目上线遗漏等错误的出现。此处推荐阅读阿图·葛文德的《清单革命》,它告诉我们如何持续、正确、安全地把事情做对。
在影响范围如此大的场景下,分享迭代项目如期上线,上线后质量稳定,满足了产品运营所预想的功能。除一次性的实现产品功能收益外,还有以下三重收益:第一,新增业务单元支持分享,只需要后端业务单元支持即可,所需的研发及测试成本成倍降低;第二,由于整个系统内,模块和代码结构清晰,不变模块增多,且更方便扩展,使得维护成本成倍降低,出现线上问题概率极大降低;第三,线上一旦出现问题,后端改造就可立刻修复,不再依赖客户端发版,解决问题速度也大大提高。具体细节,粗略评估如下表:
项目的收尾和复盘,就不再过多阐述。项目的成功,对团队和管理者自身都非常重要,团队的辛苦努力,需要馈赠以成功,而好的管理者要有能力带团队打胜仗来换取信任。本文介绍的分享项目,属于时间短、影响范围广、风险高的典型案例。虽然整个开发过程,节奏十分紧张,但得益于良好的架构设计和管理设计,我们最终还是顺利交付。
项目内采用的依赖倒置架构设计,及其推动管理流程,对大多数聚合层业务项目开发,也有很强的借鉴意义。项目过程中的思路和理念,也可以作为一个真实项目管理案例,教育团队和新人,这也是本文阐述整个改造过程的意义。
关于作者:
奇正,曾在奥多比 、百度任高级工程师,现任某互联网公司后端业务线 Leader,先后从事过 C++、Android、Golang 的开发工作。
领取专属 10元无门槛券
私享最新 技术干货