Flowness 工程进展:从需求到交付 · 阅读系列导读 →
一项工作交给下一位时,最容易丢失的未必是代码,而是代码背后的决定:这次究竟要解决什么问题,哪些约定已经确定,执行者可以改到哪里,最后又由谁判断做完。对话可以保留这些信息,却很难保证下一段工作会带上正确的一部分,更难判断后来出现的偏差源自哪一层。
Flowness 是 ToWow 的一种 Harness。它对这个问题的回答,是把交接本身做成架构。它区分采访、设计、工程方案、工程共识、计划、执行、复查、修复八个环节,为各环节设置交接物,再用共同的事件账记录阶段事实、引用和判定。各环节的共同要求,是让下一段工作接到足够具体的依据,也接到明确的权限边界。
以下用一个合成需求贯穿说明:为说明页发布入口增加本地失效链接检查,并提供发布器与编辑器共用的报告接口。这里假定新接口会改变已经冻结的发布约定,因此展开需要设计的路线;案例仅用于解释架构。
先让要求成为可接手的对象
“检查失效链接”还不足以交给执行者。引用不存在的页面算失效,页面存在但锚点不存在是否也算?外部网站暂时无法访问要不要阻断发布?报告只供人阅读,还是还要被编辑器消费?采访环节把这些不确定性收成需求简报,由需求方确认范围与完成条件。对本例而言,简报可以约定检查本地目标与锚点,外部网络检查暂不纳入,并要求发布器能据报告决定是否继续。
简报的意义不在于写得长,而在于让后续判断有一个共同起点。设计者可以据此比较方案;复查者也能据此判断“接口能返回报告”是否真的满足“发布入口能够阻断失效链接”。如果后来需求方改变外部链接的范围,这应当形成一次可追溯的需求修订,而不是在执行途中悄悄扩充任务。
八环也不是每项工作强制走完的清单。当前路由允许免设计任务直接进入工程共识;轻设计与全设计任务仍先经过设计、工程方案。轻档的章节深度裁剪是工程方案中的建议,不是整体跳过这两环。修复则由复查发现的问题触发。分级决定工作需要展开到什么深度,交接关系仍然必须成立。
图中的简报、卷宗、任务包和补丁并不都存放在账本里。文件与 Git 各自承载具体内容,事件账记录它们在工作中获得了什么地位、被哪个后续判断引用。这个区分很关键:保存一份文档不等于批准其中的决定,存在一个提交也不等于确认需求已经完成。
把上游决定压进下游任务
设计与工程方案分开,是为了避免把两种问题混在一起。设计首先回答为什么采用某种结构。本例可以选择把链接分析与发布决策分开,使同一份报告能被两个入口消费。工程方案接着落实接口、路径解析、失败语义与测试办法:报告怎样定位来源,缺失目标怎样表达,调用者怎样区分可继续的提示和必须阻断的问题。前者选择方向,后者让方向具备可实施的定义。
工程共识再把多人或多角色会反复使用的定义、关系和状态约定冻结成可引用的契约。这样,编辑器中的“失效”与发布器中的“失效”不必靠各自猜测。冻结也不意味着永远不能改;它意味着改变应有明确的新依据,让依赖旧定义的任务知道自己的前提已经变化。
计划把这些决定转成任务图:哪些产物先产生,哪些任务依赖它,完成条件是什么,允许触及哪些资源。一个负责报告接口的任务包,应当能指出采用的定义、接口约束、需要交回的产物与验证条件。它不能只有“实现链接检查”这一行标题,再期待下一位从全部历史对话中重新寻找边界。包的自包含性也不是由发布者自行勾选:发布入口会依据嵌入的包内容和内容哈希执行检查。
因此,任务包是上游决定与执行工作的接点。它保留必要引用,同时把本次任务压缩到一个可以接手的范围。执行者如果发现接口约定不成立,应该报告这个前提问题;拥有任务的执行权限,并不自动获得改写设计契约的权限。
这种交接比只传一份设计文档多了一层维护成本,却换来了更明确的可判定性。设计文档善于表达理由,任务看板善于组织待办;Flowness 进一步要求待办携带它所依据的决定,以及接受其结果的条件。计划冻结后的执行派发也依据任务的可运行集合展开,不再把整个计划简单视为一个串行执行请求。
行动依据与提交声明相互对应
任务包回答“这项任务要做什么”,上下文胶囊则回答“本次会话依据什么开始行动”。胶囊按角色从任务、当前状态与适用义务中组装材料,带上任务说明、必须交回的内容、禁止事项和相关依据。执行者需要文件与任务边界,复查者需要契约与待核对的产物;两者服务于同一项工作,却不必得到完全相同的输入。
胶囊还记录组装时的状态基线。一次组装从同一截面的投影读取所需状态,避免把先读到的任务和后读到的新约定随意拼接。这里的投影是事件账派生出的当前视图。记录基线的价值,是让后续提交能够说明:这次行动基于哪一个已知版本,而不是只留下“我看过资料”的笼统保证。
执行结束后,提交信封把方向反过来:胶囊给出行动依据,信封提交候选效果。信封关联任务、对应胶囊及产物引用,携带需要进入正式状态的领域事件与读写边界。本例中,它可以关联接口补丁、验证产物和任务完成候选,使提交门能够核对这次实现是否对应那项任务,以及所依赖的依据是否仍然成立。
信封也不能把执行者的自述全部当作事实。CLI 的提交入口将领域事件与真实 Git 提交共同派生为写集,执行者原先声明的写集可以保留用于比对;预先规划的读写资源声明则从规划阶段的声明事件派生。读取行为无法从 Git 差异中机械观察,仍要将声明放在胶囊邻域等范围约束下检查。这些证据各有所长,不能互相替代。
提交门据此运行登记的检查,接受或拒绝候选。接受之后,候选领域事件才连同接受记录进入正式可见的事件批次,并供投影更新。Git 中已经出现的补丁与账本中获准的效果是两个相连的事实;这里的接受指一次候选提交获得准入,最终是否达到原始要求仍需后面的复查判断。
这也解释了为什么需要胶囊与信封两端。只有任务包,能说明执行应当怎样开始;只有结果报告,能说明执行者认为自己做了什么。把本次依据、本次声明与可核对的产物连接起来,才能追问一次完成是否建立在正确的任务和仍有效的约定上。
复查按原因回到负责层
复查要同时看产物和承诺。接口返回了报告,但发布器忽略阻断标记,是实现偏离契约;两个入口对相对路径的解释不同,可能是工程方案没有明确基准;报告结构根本无法支持编辑器定位,则可能是设计选择遗漏了一个消费者。相似的失败现象,修补位置可以相差很远。
Flowness 用 Finding 保存问题、证据、影响范围与闭合条件,再让回流指向负责层。可以重新执行、局部修复、重规划,也可以退到工程方案、设计乃至采访。要主张更远的回流,需要说明为什么较轻的处理不足以解决原因。当前路由结合问题种类和建议层产生派发;回流分类与相应权限仍需落实,发现一条问题本身不会自动完成根因判断。
在本例中,如果只是发布器漏读一个已明确的阻断字段,修复候选应回到复查,按原 Finding 的闭合条件验证。若两个入口的路径基准从未定义,继续增加特殊分支只会隐藏缺失的约定,应当先回到能确定接口语义的层,再修订依赖它的任务。修复者交回候选,复查者核对闭合条件,这两项责任分开,问题才不会随着一句“已修复”消失。
把整条链连起来,验收获得的是一组可以追溯的对应关系:要求怎样成为契约,契约怎样成为任务,本次行动依据什么,提交获准了哪些效果,留下的问题又怎样闭合。Flowness 的设计价值就在这里:依据可以引用,权限在交接中保持边界,局部完成最终能够回到同一项要求上接受判断。