Skip to content
Published on

从定制到平台:把 FDE 的工作产品化

分享
Authors

引言 — 从一个客户到所有客户

在前两篇文章里,我们讲了前向部署工程师(FDE)是什么,以及一个用完即弃的原型如何把一个客户带到「啊哈时刻」。这篇文章要处理的是下一个问题:如何把为一个客户打造的定制工作,培育成面向所有客户的平台?

这是 FDE 组织存在的理由,也是它最难的挑战。做错了,公司就会变成一家背着和客户数量一样多、彼此互不相通的代码块的咨询公司。做对了,从现场汲取的洞见就会成为公司的核心产品。事实上,许多优秀的 B2B 产品正是沿着这条路径诞生的。

FDE 与产品之间的反馈循环

FDE 真正的价值不在代码,而在信息。FDE 是公司里最深入了解客户现实的人。哪些问题反复出现、哪些数据实际存在、客户为什么感动又为什么沮丧——这一切都积累在 FDE 的脑海与指尖。

在一个健康的组织里,这些信息会流向产品团队。

  • FDE → 产品:「五位客户都要求我们手工做这个功能。它应该成为一个产品。」
  • 产品 → FDE:「我们把那个功能做成了通用版本。下一个客户,试试用它而不是再做一次定制。」

这个循环一旦转起来,FDE 就不必每次都从零开始,产品也能依据现场证据而非想象来制定路线图。反过来,一旦这个循环断掉,FDE 就会永远重复制作同样的东西,产品也会构建出与真实需求脱节的功能。

从 N 个客户身上发现模式

产品化的起点是模式识别。一个客户的请求只是一个请求,而在多个客户身上反复出现的请求才是信号。

FDE 捕捉模式的直觉,来自这样一些问题。

  • 我是不是在给不同的客户复制粘贴同一段代码?
  • 我是不是在给每个客户重新做本质上相同的流程,只是名字不一样?
  • 是不是有几个客户说法不同,其实遇到的是同一个问题?

第三点尤其重要。客户 A 想要「合同风险审查」,客户 B 想要「供应商文档审核」,但往下看,两者也许是同一个骨架:「在长文档中找出并标记特定条件」。看穿表面词汇、看到底层结构的眼光,才是产品化的第一步。

抽取为配置与抽象

发现模式之后,下一步是把这个模式拆分为会变的部分不变的部分。不变的部分成为引擎(产品),会变的部分则落入配置(config)。

以合同条款抽取为例。不同客户之间的差异大致在于「要找哪些条款」「要归到哪些分类」「以什么格式导出」这几点。而抽取这个动作本身——调用模型并解析结果的骨架——完全相同。

于是我们这样改造定制代码:把客户之间的差异,不放进代码,而是推入声明式配置

# customers/acme.yaml — 客户专属配置(会变的部分)
customer: acme-corp
clause_types:
  - indemnification
  - termination
  - liability
output_format: csv
risk_threshold: 0.7
notify_channel: "acme-legal-slack"
# customers/globex.yaml — 不同客户,同一个引擎
customer: globex-inc
clause_types:
  - data_privacy
  - auto_renewal
output_format: json
risk_threshold: 0.5
notify_channel: "globex-procurement-email"

引擎则是读取这份配置来运行的、与客户无关的单一代码。

# engine.py — 所有客户共用的引擎(不变的部分)
def run_extraction(config: dict, documents: list[str]) -> list[dict]:
    results = []
    for doc in documents:
        clauses = extract_clauses(doc, config["clause_types"])
        flagged = [c for c in clauses if c["risk"] >= config["risk_threshold"]]
        results.extend(flagged)
    export(results, fmt=config["output_format"])
    notify(config["notify_channel"], summary=summarize(results))
    return results

这样一来,新客户到来时,不需要重新写代码,只需新增一份 YAML。定制工作就此升级为产品的配置。这正是「从定制到平台」的具体样子。

三次法则:什么时候不该泛化

这里最常见的错误是过早泛化。刚看到第一个客户的请求,就断定「大家肯定都想要这个」,开始搭建宏大的抽象。而这个抽象通常是错的。第二个客户想要的东西,和第一个微妙地不同,仓促搭出的抽象反而成了绊脚石。

因此有一条古老的智慧:三次法则(rule of three)。

  • 第一次:直接做出来。只为这一个客户,定制地做。
  • 第二次:再做一次类似的。但还不要泛化。而是观察这两个案例的共同点与差异
  • 第三次:同一个模式第三次出现时,现在才开始抽象。手上已经有三个真实案例,你可以有依据地知道什么是真正共通的、什么是客户专属的变体。

三次法则的核心在于把抽象建立在数据之上。凭一个案例想象出来的抽象是赌博,观察三个案例后建立的抽象才是设计。复制粘贴两次这点小小的重复,远比一个错误的抽象所欠下的大笔债务要便宜得多。

「重复远比错误的抽象来得便宜。」——这句格言在 FDE 的产品化判断中回响得格外沉重。

快速交付与为所有人构建之间的张力

FDE 组织的核心,存在一种根本性的张力。

  • 一边是眼前的客户。要想在这个季度签下合同,现在就得解决这个客户的问题。速度就是一切。
  • 另一边是未来的所有客户。如果每次都做定制,公司就无法扩张。必须构建可复用的产品。

这两者经常冲突,因为对当前客户而言最快的路是硬编码,而对所有人而言最好的路是泛化。成熟的 FDE 和组织不会试图消除这种张力,而是有意识地管理它。

  • 先赢下客户,但留下痕迹:这次用定制方案快速解决,但给产品留下诸如「这是第三个类似案例」这样的信号。
  • 把泛化交给产品去做:如果 FDE 在现场每次都想顺带做泛化,两件事都做不好。FDE 负责捕捉模式并移交,产品负责把它做成产品。
  • 区分一次性需求与重复需求:有些客户的需求确实只属于那个客户。这类需求就应该保持定制,而不是泛化。想把一切都产品化的欲望,恰恰会毁掉产品。

什么时候不该泛化

除了三次法则之外,还有一些情况从一开始泛化就不是答案。

  • 确实只属于那个客户时:被特定法规、特定遗留系统、特定组织结构所束缚的需求,没有被别人复用的余地。硬塞进产品只会让产品变得复杂。
  • 还没看到模式时:只有一个案例时,无法判断它是模式还是偶然。等待。
  • 不是核心价值时:不需要把每一个边缘的小便利功能都泛化。把资源集中在产品的核心价值上。
  • 泛化的成本超过收益时:灵活的抽象不是免费的。你要为此付出维护负担、复杂度,以及做错的风险。对于两三个客户,保持原样可能反而更好。

优秀产品诞生于前向部署之中

所有这些讨论最终都汇向同一个结论:许多伟大的 B2B 产品,不是在办公桌前凭空想象出来的,而是诞生于客户现场的反复实践之中。

模式是这样的。FDE 在多个客户身上反复用手工方式解决同一个问题,在这种重复之中发现了真实的需求。这个发现经由配置与抽象变成一个功能,功能不断累积成产品,产品又变成自助服务,最终客户不需要 FDE 也能自己使用。于是 FDE 转向下一个尚未开拓的问题。

这个良性循环正是 FDE 模式的终极目的。FDE 的工作方向是让自己变得不再必要。今天手工完成的事,会成为明天的产品功能;因为有了这个功能,下一个客户就再也不需要人工介入。拯救一个客户的工作,就此成长为服务数千客户的产品。

结语

从定制到平台的这条路,不会自动打开。它需要 FDE 与产品之间一个活着的反馈循环,一双能在多个客户身上读出模式的眼睛,一种能分辨什么会变、什么不变的设计直觉,一条能阻止过早泛化的三次法则,以及有意识地管理当前客户与未来客户之间张力的成熟度。

如果说贯穿这三篇文章有一个共同的信息,那就是:FDE 是一座桥梁,在客户的最前线解决真实的问题,再把这段经验回馈为面向所有人的产品。用一个用完即弃的原型赢下一个客户,再把从这场胜利中学到的东西培育成平台——这就是前向部署工程构建软件的方式。

参考资料