您还未登录! 登录 | 注册 | 帮助  

您的位置: 首页 > 软件开发专栏 > 开发技术 > 正文

软件开发提效哪有那么容易,都是坑啊

发表于:2021-05-08 作者:陶文 来源:知乎

提效就是减少浪费吗?

基于现状的各环节浪费进行分析,避免浪费,就能达到提效的目的了么?这么说未必正确,要看目的是什么。有三种可能的目的:

  1. 减少总花费:可能人变少了,但是要开发的时间变长了。
  2. 提高总吞吐:通过堆更多的人,再等同的开发时间里,交付了更多的业务价值
  3. 降低延迟:通过堆更多更多的人,不在乎有多少浪费,只要能快速响应市场就可以

不同语境下说提效,其目的可能是不同的。比如对于前段时间很火的买菜业务,大家不约而同选择的是堆更多更多的人,以降低延迟为目的,不在乎投入的方式来搞。如果为了省几个P5的工资,导致上线开城延迟了一个月,丢掉了市场,那就不值得了。

即便说提效的时候,指的就是消除浪费。如上图所示,我标记了 6个可能产生浪费的环节 。下面逐个来说每个环节产生的浪费,存在了这么长的时间都是有道理的,都没有那么容易被“提效”。不是说每一条路都走不通,而是说不存在什么低垂的果实,都有坑。

1、产品经理/UI设计师与开发者之间的交接浪费

很多人都看到了产品经理要写一遍 PRD 稿,然后开发者照着翻译一遍。UI 设计师要画 UI 稿,然后前端开发要照着还原 UI。如果能够减少这个交接环节产生的浪费,让 PRD 稿,UI 稿能直接进入下一个环节,岂不美哉。

这条路走下去的坑可能是什么?PRD 稿和 UI 稿存在的意义在于减少返工。如果没有前一道工序,让客户一句话需求直接对接开发。那很有可能做出来了,就不是客户想要的。这个时候要去改代码,比修改 PRD 稿和 UI 稿的代价要大多了。所以 PRD 稿和 UI 稿的优点就是改起来快,没有可运行的代码那么多要求,可以很随意。如果要求 PRD 稿和 UI 稿能够直接翻译执行,那势必要添加语法和语义规则限制。这可能会损害“低成本可修改可讨论”这个优点,产品经理和 UI 设计师要花更多的时间来让产出物符合规范上,而不是花更多的时间和客户讨论反复修改上。

2、开源的库和框架提供的可复用代码太少了,做过很多中后台项目,仍然有大量重复的代码

这个浪费是说,开发者复用的库和框架都是非常底层非常基础的数据结构,RPC通信这些东西。做了个几个项目之后,就会得出自己是 CRUD boy 的想法,觉得总这么重复下去不是办法。如果能够搞出几个开源的库和框架,那岂不是造福人类?

这条路走下去的坑可能是什么?开发者是无法反向约束客户需求的。任意两个客户,即便就是 CRUD 也会有不同的细微差别。比如 list / detail 是上下,还是左右,还是弹框,还是跳页?列表是分页还是无限下拉,是有筛选,还是有搜索?开源库之所以都是那些基础的东西,就是因为那些东西共性大。稍微往靠近用户的一侧靠一些,花样就百出。

然后第二个可能的想法是满足 80% 的需求,那剩下的 20% 让开发者去传参数,传 callback,写 patch,写 DSL 来满足。之前那些开源库的作者没有做到这一点,是因为他们笨(划掉),是因为我有更牛x的代码生成/组件插件技术/xxx

这条路走下去的坑可能是什么?不讨论是不是有什么牛 x 的技术就能大幅改进在已有代码上做定制的体验,我个人经验是不存在这样的技术,不管运行时的还是编译期的,能力上都基本上等价。即便有这样的技术,一方面写 20% 的人至少要知道 80% 是哪 80%,他需要知道已有的库和框架提供了什么,需求是什么,然后 diff 出 20% 的部分。然后还要知道在这个指定的库和框架上怎么写那 20%,没有两个框架提供的扩展方式是一样的,都有自己独特的搞法。

上世纪80年代的时候,流行组件市场的传说。写好业务组件,然后拿出去卖钱。但是从历史来看,最终组件市场的形态是 github 这个最大同性交友社区。最佳的代码复用方式是拿来主义,直接 fork 一份,在别人的代码基础上做修改。啥参数化,插件化,callback,都没有直接改源代码来得直接,好用。

3、现有的代码认知负担太大,新人要很长时间才能接手。反馈周期很长,没法快速修改快速迭代。

观察人是如何阅读代码修改代码的,不难得出这两个主要浪费的点。

  • 认知负担
  • 反馈周期

认知负担:代码读起来很复杂,不好理解。一份代码要交接给另外一个人来写,他要很长时间才能达到你之前的水平。甚至按照 Programming as Theory Building 的观点,没有人可以达到作者一样的理解程度。理解一份代码最好的方式可能是重新写一遍。

这条路走下去的坑是什么?有的人提议,我们需要用 Event Sourcing。有的人又提议,不对,我们应该 Reactive。有的人又提议,我们应该 Structured State Machine。每个人都会提出自己所谓的“认知负担”最低的表述方式。但是坑在于,每个人的思维习惯,过往经历是不同的。不是所有的 GUI 都一定要 React,要 Reactive,有的人,有的项目,可能 jQuery 直接改 DOM 才是“低认知负担”的解决方案。有一个说法是 Simple v.s. Easy,就是可能一个解决方案是 Simple 的,但是因为不是代码的阅读者所熟悉的模式(比如 Haskell Do Applicative),那对他来说就不是 Easy 的。编程范式这个东西,炒来炒去,就那么几种。如果有一种显著强与其他的,天下早就统一了。不存在什么未知的逻辑表述方式还没有发现出来,早就被枚举完了。

反馈周期:另外很多人也看到,修改 GUI 代码,要很长时间才能知道改得效果是什么。如果能够所见即所得,可以极大地缩短反馈周期,可以在同样的时间内,修改更多次。类似的,在本地无法获得生产环境数据,无法运行完整的代码的情况下,需要上线或者提交到某个特殊的环境才能跑,这样也会导致反馈周期很长。如果能够降低认知负担,能够缩短反馈周期,岂不美哉?

这条路走下去的坑是什么?编程语言茫茫多,运行时平台年年换,框架和库城头变幻大王旗。这些缩短反馈周期的工具和技术,都强依赖于项目使用的编程语言,运行时平台,框架和库。甚至还有可能要侵入到业务代码的逻辑代码写法。你可以在 Python 中用 viztracer,PHP 中有么,Closure 中有么?给 Html + Vue 好不容易整了个 Vite 出来,迭代速度快了,明天业务就改成用微信小程序了,之前的技术都用不上了。

4、同事之间的沟通成本很高,时间都浪费在开会上了

大型软件都不是一个人可以完成的。和同事的配合就要沟通开会。如果能够让每个人都负责一个独立的模块,模块之间松耦合,各搞各的,岂不美哉?编译的时候再把模块代码链接到一起去,变成同一个可执行文件放线上去跑。

这条路走下去的坑是什么?产品经理是不知道你们怎么拆分模块的。产品经理看到的是这里有一个界面,谁来负责这个界面的,我找谁聊需求。产品经理看到这里有一个按钮可以点,是谁来处理这个按钮点击的,我找谁聊需求。但是需求往往都是“集成需求”,就是一个模块搞不定。比如说订单详情页,需要各种各样的数据,如果这些数据都在同一个模块里,那就达不到拆分开发的目的。如果分散到了不同的业务模块里,那就得在界面上集成起来。

另外出了故障算谁的?谁来查 bug?谁来发布新代码?别人改的代码,要合并到一起,你敢上线么?

5、一个需求要很多个微服务一起配合修改,联调和上线都要小心翼翼,慢慢吞吞的搞

前面说了不拆微服务,只搞代码模块拆分有坑。那微服务就没有浪费了么?

微服务一多,就开始有人问,为啥要拆那么多个微服务。做个需求要改那么多个微服务,不但要联调,上线还有顺序依赖。一个微服务接口只要暴露出去了,就没法下掉了,天晓得哪里还有对它的引用。一个团队能完整搞定一个需求多好。要么就是单体,真香。要么就是拆分不合理,要 DDD 指导微服务的边界划分。

这条路走下去的坑是什么?没有所谓的“一个需求”。需求的粒度是人为限定的,可粗可细。不可能达到一个需求一个团队来搞定的,因为需求就没有严格的定义。同时商业创新往往是有破坏性的,就是把之前没有集成关系的集成起来,原来老死不相往来的东西,联动起来。咋调整都不可能避免团队之间配合的。

那么合微服务,减少微服务之间的 Public API 总是可以吧。比如让前端和后端同时发布,这样就不需要考虑后端 API 的兼容性问题了。合并 B 端和 C 端,这样就不用考虑 B 端没升级,C 端升了怎么兼容的问题了。

这条路走下去的坑是什么?很多运行时平台无法实现前端和后端同时发布。比如 iOS 需要审核,需要用户手动确认升级。Android 也有可能没有热更新技术。所以客户端就得兼容旧的版本,字段加了就是不能删。B 端和 C 端合并,服务端可能没人有意见。但是客户端合并到一起,无论是说同一个web域名,还是同一个微信小程序 appid,都可能引起产品经理的强烈抗议。人们习惯了给不同的角色用户,提供一个独立的端。

6、最终用户懂自己要什么,他们可以搞得定 Excel,那我们也可以把软件搞成 Excel 那样,避免因为提需求排期造成浪费

很多软件都会提供一个流程图一样的界面,让用户可以去做一些流程修改或者新建一个自动化流程,减少人工重复劳动。还可能提供一些填写数学公式的地方,让用户填填促销规则。还有一些营销页面搭建的工具,会让用户直接把页面要什么,用 Photoshop 那样直接拖拽出来。

这条路走下去的坑是什么?如果用户可以 100% 满足任意的自定义需求,那么这些“用户定制功能”,就得和专业程序员使用的工具等价。这些让用户表达需求的界面往往开发难度很大,需要投入很大的成本。而且未必产生了和成本对等的收益。在某些996国度,人们可能觉得提个需求让人来做会更快一些。

另外一个坑是用户只所以是用户,因为他们的本职工作不是“软件开发”。如果让用户定制大量的逻辑,那可能工作量会大到创造出了“全职工作”。这个时候,用户就不是所谓的“用户”了。只是另外一批专职的开发者,拿着所谓的“搭建工具”,用蹩脚地方式写代码罢了。

最大坑在于过度吹嘘这种面向最终用户,提供的定制能力,吹嘘成颠覆行业的xxx。能够快速定制的前提在于需求是固定的。只要需求超出了原先配置能力的范围,就需要引入大量的“定制”,这些定制不管是 c# 写 partial method,还是用 blueprint 拖拽流程图,关键是在于“大量”。只要定制的量上来,量变就会引起质变。所以前提一定是砍需求,不能什么需求都满足,才能达到提效。闭口不提需求限制,只吹嘘10x提效的,都是骗子。

收益总是被过度预期,成本总是被过度低估

在种种提效的努力中,看到三个常见的现象

  • 人们总是非常乐观,这个提效手段上了之后,直接就可以 10x 哇。
  • 人们又总是低估了代替现有成熟方案,模式,框架所引入的成本。这种成本投入在前半段可能完全是负产出,只有达到一定积累之后,才开始超出原有的体验
  • 不管是哪个思路去搞提效,大家都会说自己做的是“低代码”