反思产品设计中一次失败的经历

Issue

默默开发的一个 DAG (Directed Acyclic Graphs) 引擎项目 Dagrs ,在 crates.io 上发布了两个版本。从来没有在任何渠道宣传过,竟然有开发者在自己的项目中使用。最近突然收到一个 Issue 提到 DAG 任务中返回值的设计,思考之中让我对之前所做的工作进行了反思,这个项目可以说是产品设计失败的典型。

Hey! First of all, thanks for this crate and all your work for it :) In my use case it's crucial to allow individual task errors. This crate already provides the Output enum for task outputs but only uses the variant Output::Err(String) for logging. I would really like the ability to propagate the contained string value as well as the task identifier all the way to the start function. This way, a user knows failed tasks and can work with that information in his code. What do you think of this idea? I'd be happy to work on this issue.

当我准备这个博客的时候,发现邮箱收到这个开发者都邮件,可能是我没有回复他的 Issue 使得他尝试从邮件来联系我。 这些年的开发者相关工作,让我觉得老外是容易打交道的,只要真诚和对方沟通就好。


设计这个项目源自工作早期项目,经历了 Delphi 开发财务为核心的各种管理系统、SAP ERP FI/CO 实施和开发,以及极少人知道的 BMC Remedy 开发 ITSM 项目,我理解从程序角度看完成特定功能是调度函数完成任务,函数之间存在上下文的切换,函数内存在各种条件判断。如果再简化看这些函数之间的关系,它们形成了一个有向无环图,最终根据程序的输入条件生成输出的结果。所以一直有个简单的想法,通过 DAG 引擎调度程序内的函数,完成程序的基本功能。

当我尝试在 Rust 中完成这个引擎的时候,我犯了一个产品设计中最严重的错误,就是尝试引入很多特性,忽略了系统功能的边界,造成整体可用性下降和代码架构混乱。在基本功能实现后,加入了一个 YAML 脚本定义函数之间的关系以及上下文传递,在 YAML 中定义可以执行外部命令。最后甚至想把这个 YAML 改为一个可以自定的结构并且自动生成脚本解析引擎。所作的这些是想把这个定义行为的逻辑通过这样的功能传递到系统外,让使用程序的用户(也可能是另外的一个开发者)可以进行定义,这明显是超出了之前的初衷。

Less is More

23 年参加 EuroRust 2023 的时候听一个演讲提到 Flow-base Programming 的概念,研究后发现这就是我想做的事情。最近在 Discord 上看到一个 Rust 编程语言的实现 zflow,对比之下更是看到我在设计上的问题,尝试把 Flow 的控制管理交给边界之外的用户。

其实初衷我既不想做一个 Airflow、 Remedy 或是低代码平台,我只是想把烦躁重复的业务性开发简化。我面向的用户是开发者,而不是使用程序的用户。所以错误的根本是没有坚持初衷,盲目的扩大程序边界和面向的用户,贪大忘本造成了现在的局面。

我的计划

准备先删掉那些多余的功能,让整个程序只提供最基本的能力,发布一个最简版本。然后发邮件给使用这个项目的开发者,和他们讨论需求和遇到的问题,最后联合一起重构。


Issue

以上是最近项目每天 Clone 数,估计是 GitHub Action 在执行时产生的 Clone 。很多开发者都在想说如何去推广自己的开源项目,其实首先要思考项目提供的功能是什么,再去想如何解决酒香也怕巷子深的问题。


朋友圈及公众号留言精选

项目的初衷最初都是美好的,关于这个项目的抽象理念我也遇到过几个相似场景:一个是借助线程池和dag构建一个单机版的调度器,可以按照拓扑顺序并行拉起用户的udf,这个还是有需求的,可以认为是简易版的调度器。还有一个是用workflow的思路描述sql执行逻辑,informatica和MuleSoft好像做了类似的事情,有点像sql的低代码版本,但实际上开发者并不买单,所以用workflow表达高级程序语言的func call的通用性和易用性门槛就更高了。话说用DAG表达函数调用逻辑时,遇到递归可就有环了

我觉得能反思的案例太多了, 这才可怕... 总得有几个不用反思的成功,要不然亏大了

有用户就不算失败