开源二开 vs 从零自研:什么时候不该省这个钱
2022 年,我接过一个商城类项目。甲方要得很急 —— 从签约到上线,一个月。
一个月,要从零写一套“小程序 + H5 + App + PC”的商城。光是商品、订单、支付、权限、后台增删改查这些“必须有但没有差异价值”的东西,就能把整个工期吃掉。于是照惯例:找一套成熟的开源商城框架,在上面做二次开发。
项目按计划上线了。真正的麻烦是上线之后开始的。
上线后的第一周,几乎每天都在改,有几天一天发好几个版本。 改的全是业务文件 —— 积分怎么算、购买流程怎么走。这些恰恰是甲方真正在意的地方,也正是框架自己早就写好、并且默认“大家都这么干”的地方。
那段经历让我第一次认真想一个问题:二开省下的时间,和它后来还回去的时间,到底哪个更多。
我做过几个基于开源框架二次开发的系统,也做过完全从零自研的。这篇不站队 —— 二开在很多场景下确实是对的。我想讲的是那个容易被忽略的部分:你要怎么判断这一次的二开,会不会在两三年后变成一个没人敢动、也升不上去的孤岛。
二开为什么看起来总是更划算
三个账都站在二开这边。
时间账。 商品、订单、支付、权限、文件上传、后台增删改查、操作日志 —— 这些功能没有差异价值,但必须有。开源框架已经写好了。自研的话,这些做完,业务代码一行还没开始。
风险账。 一个被几万人用过的框架,边界情况已经被踩过很多遍:并发下单、超卖、支付回调重复、上传中断。你自己写的第一版,大概率没踩过这些。
成本账。 同样是三周的交付周期,自研只能做出框架第一天的功能量。
所以默认答案确实是“划算”。真正的问题是:它在什么情况下不划算。
二开的成本从哪来
一、你的业务假设和框架的业务假设不一致
这是最大的成本来源,也是最容易被低估的。
框架的代码不是一堆函数,而是一整套关于“业务应该长什么样”的假设:订单什么时候生成、库存什么时候扣、多规格商品怎么表达、一张订单能不能拆成多次发货、退款是原路返回还是余额。
你的业务只要和这些假设不一致,改动就不是“加个功能”,而是“改数据模型”。而数据模型一动,牵动的是所有依赖它的地方 —— 建表、查询、接口、报表、历史数据迁移。
判断信号其实很直接:如果需求描述里出现了“我们的规则不太一样”,那这次的估算就已经不准了。
二、升级路径会断
开源框架的更新是持续的:安全补丁、依赖升级、新能力。
但你只改了核心文件,升级就变成了手动合并。
改一个文件,还好,半小时的事。改三十个文件,就要一个下午。改到三百个,你就不升了 —— 因为每次升级的收益,看起来都远小于那一下午的风险。
更麻烦的是冲突会反复出在同一批文件上。我前面那个商城项目的改动集中在积分和购买流程的业务文件里,而这些地方正是上游框架迭代最频繁的部分。于是每次上游发版,冲突都落在同样的几个文件上:改得越多,越升不动,这个方向是单向的。
三年后回头看,你维护的已经不是“那个开源框架”,而是一个没人认识、也没人维护的 fork。安全补丁要自己从上游 cherry-pick,依赖漏洞要自己评估。这部分成本不会出现在任何一份工时估算里,但它每年都在发生。
三、扩展点决定你的改动落在哪里
同样是二开,成本差别能有好几倍,分水岭就在这里。
- 框架留了扩展点(事件、钩子、中间件、插件机制)→ 你的改动是“注册”一段自己的代码,升级时不受影响。
- 框架把逻辑写死在控制器或服务类里 → 你的改动是“修改”别人的代码,升级时全部冲突。
所以二开之前,最值钱的一两个小时不是我写代码,而是:读一遍这个框架的扩展机制文档,然后问自己 —— 我要改的东西,能不能只用“注册”完成?
如果答案是“不能”,那这一次的二开,本质上是在一个你不拥有的代码库上做一次重写。这种项目不是不能做,但你的工期和风险要按重写来估。
四、多端共用会放大前面所有问题
很多框架是围绕“一个后台 + 一个前端”设计的。
当你要的是“小程序 + H5 + App + PC 共用一套业务逻辑”时,如果业务规则散落在各端的视图层里,同一个规则你要改四遍 —— 而且四遍还可能改得不完全一样。等到线上出现“小程序算 88 折、App 算 9 折”这类问题时,排查成本会成倍上升。
这一条在多端项目里经常是真正的成本大头,但它不出现在框架的功能清单上,所以最容易被漏算。
还有一类成本不属于技术范畴:社区版与商业版的边界。有些能力看着像自带,做到一半才发现要买授权或企业版。这一条在评估阶段就该查清楚,不要留到中期。
怎么判断:该二开还是该自研
把前面的东西压缩成两组信号。
应该重新考虑自研的信号(这时候不该省这个钱)
- 你的核心竞争力就在数据模型上 —— 计价规则、库存分配、履约流程跟别人不一样
- 你的主流程和框架的假设是反向的,而不只是“多一个分支”
- 你要多端共用同一套业务内核
- 这个系统要长期迭代(两年以上),不是交付即止
- 框架没有稳定的扩展点,改动必须进核心文件
这五条里,第 1 条和第 5 条同时成立时,二开基本可以排除。核心差异长在别人的代码里,是最难处理的一种结构。
二开明显划算的信号(该省这个钱)
- 需求落在框架能力范围内 —— 标准商城、标准预约、标准后台
- 一次性交付型项目,验收即结束,后续改动很少
- 差异主要在展示层和配置层,不动数据模型
- 有明确的上线时间压力,需要先跑起来再迭代
最常用的是中间路线:二开外壳 + 自研内核。
框架负责它真正擅长的部分:后台增删改查、权限、文件、日志、基础订单结构。
把有差异的业务逻辑 —— 计价、库存分配、履约状态流转 —— 抽成独立的模块或服务,不写在框架的控制器里。
好处很具体:升级的时候,你的改动面是被隔离的、可控的。框架升级只影响外壳,内核是你自己的。
代价是前期多花一些设计时间。这笔钱通常值得花 —— 它换来的是未来三年里每一次升级的可行性。
如果决定二开,这几条能省下后面的钱
- 只改扩展点,不改核心文件。 实在必须改核心文件时,把所有改动集中在一个目录里并逐条记录,升级时好对照。
- 数据模型只加不改。 需要新语义就加表、加字段、加适配层,不要改原字段的含义。改语义是升级冲突的头号来源。
- 业务逻辑不要写在框架的控制器里。 控制器越薄越好,那是别人的地盘。
- 建一个上游更新记录。 每次上游发版,花半小时评估一次影响。半小时的成本,比三年后一次性面对整套冲突低得多。
- 先评估,再承诺工期。 读扩展机制、找核心冲突点、判断改动面 —— 这一两天不该省,它是整个项目里性价比最高的一两天。
这套判断的边界
上面整套逻辑是写给“长期迭代的业务系统”的。有两种情况它不适用:
- 一次性交付、客户只要求能用。 这时候二开的性价比极高,前面那些关于升级和扩展点的担忧基本不会发生。
- 极早期验证。 你需要的是最快看到东西能不能跑起来,不是最干净的结构。先做出来。
反过来也成立:如果你的卖点就是这个系统本身,核心部分自研没有商量余地。你不会希望自己产品里最值钱的那块,长在别人的代码里。
小结
二开和自研不是技术偏好问题,是成本什么时候付的问题。
二开的成本不是不存在,它只是被推迟了 —— 推迟到你改了核心文件、升不动级、或者要把同一个规则改四遍的那一天。
判断的核心就一句:你的改动是落在扩展点上,还是落在核心文件里。
前者几乎总能省下钱,后者迟早要连本带利还回去。
评论
说说你的看法,或补充一个你遇到过的类似情况。