13 章节11: 项目切分
雷欧雷欧 保存 显示目录
在之前的章节中,我们通过优先完成一个个的集成片来快速启动项目,这个技巧在开发过程中可以被普遍使用。
结构划分优于成员划分
当我们在做任务分组时,往往会按照成员来进行划分,给工程师一个任务清单,再给设计师一个任务清单。这就会导致我们在前一章中提到的问题,大家明明完成了很多任务,但是却没有办法将它们组成一个实质性的成果。
举一个与软件程序无关的例子。假设我们要组织一场筹款活动,现在需要为三名志愿者每人创建一个任务清单来追踪他们的工作进展。但是这么做有一个问题,我们无法看到整个准备工作的进度。因此,我们应该从结构层面创建清单——每个清单都应该是相对独立的时间。换言之,我们应该按照菜单、场地、声光来创建清单,组织者可以一目了然什么任务已经完成了以及是否在哪个问题上遇到了突发情况。
在程序开发中,我们对于开发的内容往往都是没有经验的,这样就很难预先将项目划分好。这些项目就像是地图中的荒野地带一样,当我们探索后才能绘制出来。但是通过对工作的深入研究,我们逐渐摸索到了事物间的联系以及该如何去对项目进行切割。
前一章中,我们在项目的切片里对前端和后端进行了集成,这就使得我们可以在落实一部分成果后再继续推进。这样做显然比埋头做任务,然后在周期最后才祈祷任务结果可以拼凑在一起要靠谱多了。
我们将这些项目的切片叫做项目分区,项目的整体范围被我们切割成了许多可以独立完成的小分区。在这一章中,我们将了解开发组是如何将项目进行分区并逐一完成它们的。
分区规划图
在最开始的时候,我们俯瞰项目时只有一个模糊的轮廓。没有具体的任务也没有分区。
当开发组成员接手项目后,就会开始搜寻任务。从任务开始着手是很自然的一个选择,它们就是非常具体的一个个颗粒散布在项目的轮廓中。但是现在就将它们进行分组还是为时过早了,我们不必刻意的去将它们归类,目前更需要专注于尽可能多地发掘任务。
但我们并不会在这个阶段停留太久,这张图还是过于模糊,从更高层级来看,我们并不能获取到有效的信息。
当开发组实际上手工作后,他们很快就会理清楚任务间的关联以及项目的构造。接下来就可以将项目拆解成分区了。这就像把项目图分割为独立的区域。
分区能够准确的反馈出它所承担的职责,并且开发组通常在短时间(几天甚至更少)内就能完成一个分区。相比于任务,分区的体量更大,但是相比于项目,它们又更加的精简。
这个俯瞰图只是我们的构想的一个画面,在实际工作中,我们会将分区创建为任务清单,每个分区都对应着一个清单名,分区内的任务都会移动到对应的任务清单中。
项目语言
除了作为项目的切片外,分区也成为了一种宏观层面上的项目语言。在有了这些分区名称后,你可能会听到开发组在沟通中频繁地使用到项目语言:「在 Bucket Access 完成后我们就可以实现 Invite Clients。当有公司成员拨动了 Visibility Toggle,我们就会对 Recording Visibility 进行更新。」
当需要报告项目进展时,开发组也可以通过这种项目语言来说明已完成和未完成的工作。这样我们就不必纠结于具体任务的细枝末节,我们的关注度是在更高的分区层级,这样的汇报显然更令人满意,同时也不会干扰到尚未完成的独立任务。(我们会在下一章中更细致地说明如何利用山形图来汇报分区完成情况。)
案例分析:信息草稿
一名设计师与一名程序员正在开发一个新功能:一个新的应用需要支持创建和保存消息草稿。在开工后,他们将需要完成的任务规划成了不同关键点。
在第一周结束时,他们已经完成了许多任务,但是他们却没有什么可以展示的成果。基于「尽快获取成果」这一理念,他们决定集中精力做一个可以独立体验的分区内容:创建一个新草稿。
他们将这个新分区叫做「Start New」,他们为其创建了一个任务清单,并将待完成的任务移动到清单中。现在他们只剩下了一个设计任务就可以完成这个分区。
在这个设计任务完成后,这个分区也就完成了。
剩下尚未归入分区的任务也并不代表着就是项目剩余的所有任务了。当他们开始处理这些任务时还会诞生更多的任务。尽管如此,这里要继续划分分区也是绰绰有余的。为了能让自己的工作成果尽快展现出来,开发组成员也希望在原有的分区基础上进行调整。
在检阅了剩余任务后,他们决定将与「搜索草稿」相关的任务划进「查询」的分区中,把「删除」相关的任务划进「回收站」的分区中。其余的任务看来都和保存与编辑草稿有关,所以就叫做「保存/编辑」。
再看看「搜索」分区。这里目前只有一个任务。但我们真正动工后,就会遇到更多的,这些任务在最开始规划关键点时是想不到的。
当设计师开始进行「搜寻」的工作时,程序员则专注于开发「保存/编辑」。随着对这个问题的挖掘逐渐深入,她发现可以再剥离下一些项目切片进行开发以快速产出一些可见的成果。这一个分区实际上可以一分为三。
首先,她将和发送草稿信息有关的任务提炼出来归位「发送」。
这样一来,「保存/编辑」中剩下的任务一些是关于存储信息的,其它的则是无关的。于是她再次划分了两个分区:「存储」与「回复」。在回复另一条消息时调用草稿则是一个特殊场景。
这时,开发组发现他们可以从一个高层级来俯瞰这个项目的规划了。所有重要部分都可以在宏观层面看作是分区。这些精简的分区保证了不会有任何重要的任务被遗漏掉。
与此同时,设计师也在「搜索」上取得了进展。在一些布局完成后,它们就可以被标记为完成可。「发送」与「存储」的任务也同样会被完成。
一旦「发送」与「存储」部分完成,就只剩一些关于「回收站」与「回复」的任务了。
接下来就可以完成整个项目了。
探索分区
分区是无法凭空规划的。在切分之前你需要在这个部分实际摸索看看。我们进行分区也并非是为了保持整洁而进行分组分类,而是为了寻找到事物的独立完成的坑行,进而找到各部分间的潜在依赖和关联。
分区是源于相互依赖关系的。各部分之间的依赖模式决定了你何时才能宣布这部分切片被被「完成」了。但你是无法预见真正的内容和它们之间的关联的。我们在稍早前探讨过预想中的任务与现实中的任务,分区也同样适用于这个原则。我们需要实际的工作和观察才能摸索出分区以及事物间的关联性。
这也就是为什么我们并不期望在项目的一开始就能得到一个准确的划分。这个答案我们的预期时间是在项目启动两周后,开发组在接触到了实际的工作后会更加容易接触到事物间天然的分界线。
在项目一开始遇到一些反复与不稳定的情况也是很正常的。当开发组摸索到真正的分界线后,分区也会随之重新划定并重新命名,就像上面的例子中所示,开发组将注意力集中在了「存储与编辑」的具体问题上了,因此很容易就走向了这个分区。但直到他们陷入了困境才注意到「发送草稿」的任务其实应当单独创建分区。
如何确定项目分区是否得当
一个切割得当的分区体系能够有效地帮你梳理清楚项目结构。就像你的身体感觉到疼痛时,你会自然而然地知道是哪一个部位,因为你太了解自己的身体构造了。项目也是一样的,你的设计、采用的系统以及问题间的依赖性也会赋予你的项目一个自然生成的结构体系。
我们有三种标志可以用来判断分区是否得当:
- 整个项目尽收你眼底,丝毫不担心细节中藏有重大隐患。
- 分区语言让关于项目的讨论更加流畅。
- 每个分区就像篮子一样,你很清楚每个新任务应该丢进哪里。
我们同样有三个标志来判定分区存在问题:
- 难以界定如何才算「完成」一个分区。这种情况往往表现为任务在同一个分区中却毫无关联,完成一个任务并不会将你引导至下一个。此时你应该尝试对分区进一步地分离,就像我们在「草稿」的案例中所做的那样。
- 分区的名称在项目中并不具备独立性,比如「前端」或者「bug」。我们将这种分区称之为「福袋」或者「杂物间」。这个现象也意味着分区的集成度是不够的,这样你永远无法将一个分区标记为「完成」。我们以「bug」为例,我们需要将它拆分到具体的分区中,这样才能判断这些 bug 是否会影响到分区的完成,是否要优先修复。
- 分区切割地太过粗糙。如果一个分区划分得太大了,那就和项目没有区别了,里面会有着一串长长的任务清单。为了更快抵达胜利终点,我们最好能将它切割地再细致一些。
这章的最后让我们再来看一些通用的小技巧吧。
夹心蛋糕
大多数软件项目都需要一些前端设计和一层简洁的代码来支撑。试想有这么一个数据库应用,你需要的操作只有输入内容、保存内容、显示内容。这样的项目就像夹心蛋糕一样:因为后端的工作简洁且分布均衡,所以你可以直接通过前端设计来预估后端工作量。在这类场景中,你可以把前后端任务都集成到一个分区中。对于大多数「信息系统」类型的应用来说,这都是很棒的默认方式。
冰山
但有时后端工程量会比前端的大得多, 或者反过来。举个例子,一个新功能,它所需要的只是提交一个表单,但是要获取一个准确的答案其实需要经过非常复杂的商务运算逻辑,这种项目结构就像是一座冰山。
对于冰山类型的项目,可以讲前端先剥离出来作为一个独立的工程分区(假设前端和后端的关联性并不复杂)。如果后端确实很复杂,也可以将其划分出不同的关键点,并分别划分为分区。在这种场景下,你的目标就是为不同阶段找到你可以单独「完成」的内容,而不是等到项目尾声才祈祷任务可以拼装到一起。
有时候你还会遇到上下颠倒的冰山。前端非常复杂而后端则相对简单。比如说,日历的数据模型并不复杂,但是呈现一个多日事件与不同单元格间的交互则需要前端花费大量的时间解决问题。
无论是哪种冰山,我们都需要优先思考复杂度的必要性。我们真的需要这么花哨的前端界面么?后端的模型是否可以进行优化呢?
杂物区
总会有那么一两个任务难以放入任何范围中。我们允许创建一个「杂物」清单来放置这些难以加入其他区块的零散任务。但我们需要随时留意这个区域,如果任务数量超过了三五个,我们就应当反思是否在某处应该另行切割一个分区了。
用「~」来标记锦上添花的内容
新任务会随着我们对项目的深入挖掘不断产生。有些问题是会一直伴随着你永无止境的,比如代码的清理,边缘场景的兼容,现有功能的改进。解决这些待改进内容最好的办法就是把它们放进一个分区中,并标注上一个「~」。所有人都可以区「锦上添花」的任务清单中寻找「必不可缺」的。
如果没有截止日期,我们就会走进无限改进的怪圈。但有了时间限制,我们就必须手握利刃快刀斩乱麻来控制膨胀的分区。在某个任务甚至是某个分区前标注「~」就是我们最好的利刃。在第十三章中介绍如何控制分区时我们会继续讨论这个技巧。