甘特图中的依赖关系:四种类型
依赖关系规定谁等谁。你能在甘特图上画出来的关系一共四种,其中一种承担了大约九成的工作,另外三种是为它处理不好的场合准备的。下面逐一说明每种的含义,全文用同一个真实项目贯穿,并补上多数讲解都会跳过的两件事:滞后量与提前量的区别,以及总浮动时间与自由浮动时间的区别。
贯穿全文的那个项目
依赖关系的示意图人人看得懂,一到自己的计划上就用不出来。所以这里用一个真实项目把四种类型全部走一遍:某市地铁 3 号线的信号系统升级割接。六项任务,按工作日计,2026 年 3 月至 4 月。
信号系统升级割接。六项任务,工作日,2026 年 3-4 月。
| # | 任务 | 开始 | 结束 | 天数 |
|---|---|---|---|---|
| 1 | 编写数据迁移程序 | 3 月 2 日(周一) | 3 月 13 日(周五) | 10 |
| 2 | 迁移试运行(实验线联调) | 3 月 16 日 | 3 月 20 日 | 5 |
| 3 | 修复试运行发现的缺陷 | 3 月 23 日 | 4 月 3 日 | 10 |
| 4 | 编写割接作业手册 | 3 月 16 日 | 4 月 3 日 | 15 |
| 5 | 行车调度员培训 | 3 月 23 日 | 3 月 27 日 | 5 |
| 6 | 旧信号系统保持运行 | 3 月 2 日 | 4 月 6 日 | 26 |
六条横条,一条连线也没有:到这一步为止,这张图还没有说出任何一件事依赖另一件事。正式割接安排在 4 月 6 日夜里的天窗点, , 末班车之后、首班车之前的那几个小时,是全线唯一能动信号设备的时间。这个约束会在下面每一种依赖类型上留下痕迹。
完成-开始(FS), , 你真正会用的那一种
任务 B 必须等任务 A 完成之后才能开始。刮完腻子才能刷漆。
任务 2 是任务 1 的 FS 后继:没人写出来的程序没法拿去联调。任务 3 又是任务 2 的 FS 后继,因为缺陷清单在试运行跑出来之前根本不存在。1 → 2 → 3 这条链,十天加五天加十天,是整个项目的脊梁,也决定了 4 月 3 日这个结束日期。
FS 是所有排程工具的默认值。如果你拿不准该用哪一种,那多半就该用它。急着去找一种冷门类型,往往说明任务的拆分方式有问题,而不是说明你真的需要 SS 或 FF。
开始-开始(SS), , 同时展开的工作
任务 B 必须等任务 A 开始之后才能开始,此后两者并行推进。
割接作业手册(任务 4)是试运行的 SS 后继。编写手册的人需要试运行已经在跑才有东西可写,但如果等它结束就白白浪费一周,所以两者都从 3 月 16 日(周一)开始。
什么时候用 SS:B 只等 A 起步。土方一开挖,监理就要进场旁站;主体一开工,安全巡查同步启动。判断标志是两件事共用一个触发点,而不是共用一个截止时间。
完成-完成(FF), , 必须一起收口的工作
任务 B 必须等任务 A 完成之后才能完成。
割接手册对任务 3 还有一条 FF 连线:只要缺陷还在陆续修复,手册就不能定稿,因为每修一个缺陷都会改写手册里的一步操作。于是它一直开着,直到 4 月 3 日(周五), , 由试运行拉开,由缺陷修复收口,这正是一切伴随性工作的形状。
测试不能早于开发结束、文档随功能一起收尾、监理资料随分项工程一起归档,都是 FF。B 什么时候开始都行,它只是不能先冲过终点线。
开始-完成(SF), , 最少见的那一种
任务 B 必须等任务 A 开始之后才能完成。读起来是反的,多数计划人员一辈子也用不上一次。
任务 6 恰恰是它被发明出来要解决的情形。旧信号系统必须一直运行到新系统投用为止:它的结束钉在割接的开始上。用 SF 连起来之后,天窗点无论最终落在哪一夜,旧系统那条横条都会自动伸长过去,不需要任何人记得手工拖它。
这就是诚实的判断标准:一次交接, , 旧的东西之所以结束,是因为新的东西开始了。除此之外的场合,先检查一下把顺序调过来能不能用一条普通的 FS 说清楚同一件事。
四种类型对照
| 类型 | 现实中的触发条件 | 使用频率 | 它会诱发的错误 |
|---|---|---|---|
| FS 完成 → 开始 | A 的产出就是 B 的输入, , 一份缺陷清单、一张签发的图纸、一段浇筑完成的结构 | 约占普通计划连线的九成 | 把偏好当成约束来连,直到每个日期都被钉死、再也无法重新规划 |
| SS 开始 → 开始 | 两项工作共用一个触发点,此后并行推进 | 常见,多数计划里都有几条 | 它只对前置任务的开始作出反应。前置任务结束推迟时,后继一动不动 |
| FF 完成 → 完成 | 包裹在外面、不能先于被包裹工作收口的活动, , 测试、文档、验收资料 | 偶尔,多为伴随性任务 | 不约束 B 的开始,于是图上看起来它可以早得离谱地启动 |
| SF 开始 → 完成 | 一次交接, , 旧班组、旧系统、旧合同因为新的开始而结束 | 罕见。很多正确的计划里一条都没有 | 被当成"反着写的 FS"来凑合用,而评审计划的人没有一个读得对 |
类型选错时,计划会说谎
现在看任务 5,行车调度员培训。计划人员把它连成了任务 3 的 SS 后继:缺陷修复一开始,培训就开始。看上去没问题, , 两条横条都从 3 月 23 日起,3 月 27 日全员培训完毕,离割接还早得很。
然后试运行发现的问题比预想多,任务 3 从十天变成十五天,结束日期从 4 月 3 日推到 4 月 10 日。
- 任务 4(割接手册,FF), , 跟着动了,结束日期顺延到 4 月 10 日。正确。
- 任务 5(培训,SS), , 纹丝不动。SS 盯的是前置任务的开始,而开始并没有变。计划上仍然显示调度员在 3 月 27 日就完成了培训。
图并没有坏,它只是老实回答了你问它的那个问题。可现实是:调度员正在一套还有两周缺陷要修的系统上接受培训,而计划把这件事报成绿色。正确的连法是任务 3 的 FS 后继, , 等软件不再变化了再培训人。一个字母之差,把一个两周的隐患变成了"没有隐患"。
所以要专门试一次。计划连完线之后,把最可能超期的那项任务拉长一周,看看什么跟着动了。凡是你以为会动却没动的,都是类型选错, , 而现在改还不花钱。
提前量与滞后量:滞后不是余量
滞后量给连线加上等待时间。"FS + 3 天"表示 B 在 A 结束三天后才开始。在我们这个项目里,割接是缺陷修复的 FS+1d 后继:留出一整天做最后一次数据同步。
最容易搞错的一点:滞后量不是浮动时间。浮动时间是出事时你可以花掉的余量;滞后量是已经承诺出去的时间, , 混凝土养护、油漆干燥、合同约定的审查期。谁也不能在拖期时"用掉"一段滞后量,混凝土该养护几天还是几天。因为某项任务"可能超期"就在连线上加滞后量,等于制造了一笔谁也找不到、谁也砍不掉的储备。
提前量是负的滞后量:"FS − 2 天"让 B 与 A 的尾巴重叠。提前量能压缩工期, , 所谓的赶工搭接就是这么做的, , 但它是用风险换时间。一个没有想清楚的搭接就是一条返工队列:B 是在一个还没做完的 A 上面施工。
两者在 MS Project 记法里都写作 3FS+2d, , 第 3 行、完成-开始、滞后两天。gantts.app 的前置任务列直接接受这种写法。
总浮动时间和自由浮动时间不是同一个数
连线画好之后,每项任务都有了浮动时间:它可以推迟多久才会伤到别的东西。这个"多久"有两种,混为一谈的代价很高。
总浮动时间是一项任务在项目完工日期开始移动之前可以推迟多久。自由浮动时间是它在自己的紧后任务开始移动之前可以推迟多久。自由浮动时间永远不会更大,而两者之间的差额正是麻烦藏身的地方。
改正之后的计划里,培训是有总浮动时间的, , 完工日期由缺陷链决定。但总浮动时间是共享的:如果连着三项任务各显示八天,那是三项之间一共八天,不是二十四天。只看这个数字就自作主张推迟一周的负责人,花掉的是整条链的浮动时间,而账要记在最后一项头上。
总浮动时间为零,就是关键路径的定义。在 gantts.app 里勾上关键路径,这条链会画成斜纹。这也正是类型必须选对的地方,因为它就是决定完工日期的那条链。
在 gantts.app 里创建和编辑依赖关系
- 从横条拖到横条。按住任务横条边缘的小圆点,拖到目标横条上松手。连线以 FS、滞后量为零的形式建立。
- 改类型。点两条横条之间的箭头,连线编辑器打开,类型下拉里有四项:FS · 完成 → 开始、SS · 开始 → 开始、FF · 完成 → 完成、SF · 开始 → 完成。图会立即重绘。
- 加滞后量。同一个编辑器里的滞后(天)。割接前那一天写
1,提前量写负数。两者都可以用 Ctrl+Z 撤销。 - 也可以直接敲。表格里的前置任务列按行号接受写法:
3、2SS、3FF、3FS+2d,多个用逗号分隔。刚粘贴进来一份计划时,这是最快的连线方式。 - 或者用任务面板。点开任务,展开前置任务,下拉里选一项就加一条连线,每一条都有自己的类型选择器。
- 删除。连线编辑器里的删除按钮,或者任务面板里对应条目旁边的 ✕。
有一个行为值得先知道:在这里添加依赖关系只能把任务往后推,永远不会把它往前拉。排程是"按摆放位置"计算的, , 任务的开始时间取"你拖到的位置"和"前置任务允许的最早位置"当中较晚的那个。如果一条横条本来就摆在前置任务之后很远的地方,连上线之后它不会动,中间的空档保持原样。这是刻意的:你有意摆好的横条,不应该因为你为了出报表补了一条连线就被拽走。要把整份计划压实,点自动排程, , 它不管依赖任务现在摆在哪里,一律拉回到前置任务允许的最早日期,同时把没有连线的任务留在原地当锚点。
常见问题
甘特图有哪几种依赖关系?
四种:完成-开始(FS)、开始-开始(SS)、完成-完成(FF)、开始-完成(SF)。FS 覆盖了现实中绝大多数关系;SF 确实罕见,很多正确的计划里一条都没有。
提前量和滞后量有什么区别?
滞后量是加在连线上的等待时间, , FS+3d 表示后继任务在前置任务结束三天后开始。提前量是负的滞后量,让两者重叠。要点在于:滞后量是已经承诺出去的时间,不是余量,拖期时你并不能把它花掉。
总浮动时间和自由浮动时间有什么区别?
总浮动时间是一项任务在项目完工日期移动之前可以推迟多久;自由浮动时间是它在自己的紧后任务移动之前可以推迟多久。总浮动时间沿整条链共享, , 三项任务各显示八天,并不意味着它们之间有二十四天。
默认该用哪种依赖类型?
完成-开始。如果觉得非用别的类型不可,先检查任务拆分得对不对, , 需要冷门类型,往往是某项任务本该拆开的征兆。
在 gantts.app 里加了依赖关系,日期会怎么变?
依赖关系只能把任务往后推,不会往前拉:任务的开始取"你摆放的位置"和"前置任务允许的最早位置"中较晚的一个。想把依赖任务压回最早的合法日期,点"自动排程"。
怎么添加依赖关系?
从任务横条边缘的小圆点拖到另一条横条上,或者在"前置任务"列里直接写 3FS+2d 这样的记法。点任意一条连线箭头,可以改它的类型和滞后天数,也可以删除它。
相关模板
延伸阅读
本文也提供英文版本。