回顾我这三年,都是泡沫
昨天,一个在掘金认识的小伙伴,进入了美团专门做 IDE 的基建组,心底真是替他高兴,这本来就是他应得的。
刚认识的时候还是一个工作一年的小毛孩,整天逮着我问各种问题,模板引擎、Babel、Electron、Jest、Rollup…
虽然没见过面,不知道他长什么样,在我脑海里,他就是两样放着光,对技术充满好奇心、自我驱动力很强小伙子。
我就知道他能成,因为我多少也是这样子的,尽管我现在有些倦怠。
后来,随着工作越来越忙,博客也停更了,我们便很少联系了。
不过,后面我招人,尤其是校招生或者初级开发,我都是按照他这个范本来的。我也时常跟别人提起,我认识北京这样一个小伙子。
也有可能我们这边庙太小了,这样的小伙伴屈指可数。
好奇心和平台一样重要。
大部分人智商条件不会有太多的差距,尤其是程序员这个群体,而好奇心可以让你比别人多迈出一步,经过长时间的积累就会拉开很大的差距。
而平台可以让你保持专注,与优秀的人共事,获得更多专业的经验和知识、财富,建立自己的竞争壁垒。
回到正题。
我觉得是时候阶段性地总结和回望回顾我过去这三年,却发现大部分都是泡沫。
2020 年七月,口罩第二年。我选择了跳槽,加入了一家创业公司
跨端开发的泡沫
2020 年,微信小程序已经成为国内重要的流量入口,事实也证明,我们过去几年交付的 C 端项目几乎上都是小程序。更严谨的说,应该是微信小程序,尽管很多巨头都推出了自己的小程序平台,基本上都是陪跑的。
Taro 2.x
进来后接手的第一个项目是原生小程序迁移到 Taro。
那时候,我们的愿景是“一码多端”,期望一套程序能够跑在微信小程序、支付宝小程序等小程序平台、H5、甚至是原生 App。
那时候 Taro 还是 2.x 版本,即通过语法静态编译
成各端小程序的源码。
我们迁移花了不少的时间,尽管 Taro 官方提供了自动转换的工具,但是输出的结果是不可靠的,我们仍需要进行全量的回归测试,工作量非常大。 期间我也写了一个自动化代码迁移 CLI 来处理和 Lint 各种自动迁移后的不规范代码。
重构迁移只是前戏。难的让开发者写好 Taro,更难的是写出跨端的 Taro 代码。
我总结过,为什么 Taro(2.x) 这么难用:
- 很多初级开发者不熟悉 React。在此之前技术栈基本是 Vue
- 熟悉 React 的却不熟悉 Taro 的各种约束。
- 即使 Taro 宣称一码多端,你还是需要了解对应平台/端的知识。 即使是小程序端,不同平台的小程序能力和行为都有较大的区别。而 Taro 本身在跨端上并没有提供较好的约束,本身 Bug 也比较多。
- 如果你有跨端需求,你需要熟知各端的短板,以进行权衡和取舍。强调多端的一致和统一会增加很多复杂度, 对代码的健壮性也是一个比较大的考验。
- 我们还背着历史包袱。臃肿、不规范、难以维护、全靠猜的代码。
在跨端上,外行人眼里‘一码多端’就是写好一端,其他端不用改就可以直接运行起来,那有那么简单的事情?
每个端都有自己的长板和短板:
我们从拆分两个维度来看各端的能力:
放在一个基线上看:
跨端代码写不好,我们不能把锅扔给框架,它仅仅提供了一种通用的解决方案,很多事情还是得我们自己去做。
实际上要开发跨平台的程序,最好的开发路径就是对齐最短的板,这样迁移到其他端就会从而很多,当然代价就是开发者负担会很重:
为了让开发者更好的掌握 Taro, 我编写了详细的 Wiki, 阐述了 React 的各种 trick、Taro 如何阉割了 React、Taro 的原理、开发调试、跨端开发应该遵循的各种规范。
Taro 3.0
我们的 Taro 项目在 2020 年底正式在生产使用,而 Taro 3.0 在 2020 年 / 7 月就正式发布了,在次年 5 月,我们决定进行升级。
技术的发展就是这么快,不到 5 个月时间,Taro 2.x 就成为了技术债。
Taro 2.x 官方基本停止了新功能的更新、bug 也不修了,最后我们不得不 Fork Taro 仓库,发布在私有 npm 镜像库中。
Taro 2.x 就是带着镣铐跳舞,实在是太痛苦,我写了一篇文档来历数了它的各种‘罪行’:
- 2.x 太多条条框框,学习成本高
- 这是一个假的 React
- 编译慢
- 调试也太反人类
- …
Taro 3.x 使用的是动态化的架构,有很多优势:
3.x 架构 和数据流
- 动态化的架构。给未来远程动态渲染、低代码渲染、使用不同的前端框架(支持 Vue 开发)带来了可能
- 不同端视图渲染方式差异更小,更通用,跨端兼容性更好。
- 2.x 有非常多的条条框框,需要遵循非常多的规范才能写出兼容多端的代码。3.x 使用标准 React 进行开发,有更好的开发体验、更低的学习成本、更灵活的代码组织。
- 可以复用 Web 开发生态。
使用类似架构的还有 Remax、Alita、Kbone, 我之前写过一篇文章实现的细节 自己写个 React 渲染器: 以 Remax 为例(用 React 写小程序)。
而 Taro 不过是新增了一个中间层:BOM/DOM,这使得 Taro 不再直接耦合 React, 可以使用任意一种视图框架开发,可以使用 Vue、preact、甚至是 jQuery, 让 Web 生态的复用成为可能。
升级 3.x 我同样通过编写自动化升级脚本的形式来进行,这里记录了整个迁移的过程。
重构了再重构
我在 2B or not 2B: 多业态下的前端大泥球 讲述过我们面临的困境。
21 年底,随着后端开启全面的 DDD 重构(推翻现有的业务,重新梳理,在 DDD 的指导下重新设计和开发),我们也对 C 端进行了大规模的重构,企图摆脱历史债务,提高后续项目的交付效率
上图是重构后的结果,具体过程限于篇幅就不展开了:
- 基础库:我们将所有业务无关的代码重新进行了设计和包装。
- 组件库:符合 UI 规范的组件库,我们在这里也进行了一些平台差异的抹平
- api: Taro API 的二次封装,抹平一些平台差异
- utils: 工具函数库
- rich-html、echart:富文本、图表封装
- router:路由导航库,类型安全、支持路由拦截、支持命名导航、简化导航方法…
- …
- 模块化:我们升级到 Taro 3.x 之后,代码的组织不再受限于分包和小程序的约束。我们将本来单体的小程序进行了模块的拆分,即 monorepo 化。按照业务的边界和职责拆分各种 SDK
- 方案:一些长期积累开发痛点解决方案,比如解决分包问题的静态资源提取方案、解决页面分享的跳板页方案。
- 规范和指导实现。指导如何开发 SDK、编写跨平台/易扩展的应用等等
巨头逐鹿的小程序平台,基本上是微信小程序一家独大
跨端框架,淘汰下来,站稳脚跟的也只有 taro 和 uniapp
时至今日,我们吹嘘许久的“一码多端”实际上并没有实现;
大而全 2B 业务的泡沫
其实比一码多端更离谱的事情是“一码多业态”。
所谓一码多业态指的是一套代码适配多个行业,我在 2B or not 2B: 多业态下的前端大泥球 中已经进行了深入的探讨。
这是我过去三年经历的最大的泡沫,又称屎山历险记。不要过度追求复用,永远不要企图做一个大而全的 2B 产品
低代码的泡沫
2021 年,低代码正火,受到的资本市场的热捧。
广义的低代码就是一个大箩筐,什么都可以往里装,比如商城装修、海报绘制、智能表格、AI 生成代码、可视化搭建、审核流程编排…
很多人都在蹭热点,只要能粘上一点边的,都会包装自己是低代码,包括我们。在对外宣称我们有低代码的时候,我们并没有实际的产品。现在 AI 热潮类似,多少声称自己有大模型的企业是在裸泳呢?
我们是 2B 赛道,前期项目交付是靠人去堆的,效率低、成本高,软件的复利几乎不存在。
低代码之风吹起,我们也期望它能破解我们面临的外包难题(我们自己都在质疑这种软件交付方式和外包到底有什么区别)。
也有可能是为了追逐资本热潮,我们也规划做自己的 PaaS、aPaaS、iPaaS… 各种 “aaS”。
但是我们都没做成,规划和折腾了几个月,后面不了了之,请来的大神也送回去了。
在我看来,我们那时候可能是钱多的慌。但并没有做低代码的相关条件,缺少必要的技术积累和资源。就算缩小范围,做垂直领域的低代码,我们对领域的认知和积累还是非常匮乏。
在这期间, 我做了很多调研,也单枪匹马撸了个 “前端可视化搭建平台”:
由于各种原因, 这个项目停止了开发。如今社区上也有若干个优秀的开源替代物,比如阿里的低代码引擎、网易云的 Tango、华为云的 TinyEngine。如果当年坚持开发下去,说不定今天也小有成就了。
不管经过这次的折腾,我越坚信,低代码目前还不具备取代专业编程的能力。我在《前端如何破解 CRUD 的循环》也阐述过相关的观点。
大型项目的规模之大、复杂度之深、迭代的周期之长,使用低代码无疑是搬石头砸自己的脚。简单预想一下后期的重构和升级就知道了。
低代码是无代码和专业编码之间的中间形态,但这个中间点并不好把握。比如,如果倾向专业编码,抽象级别很低,虽然变得更加灵活,但是却丧失了易用性,最终还是会变成专业开发者的玩具。
找对场景,它就是一把利器。不要期望它能 100% 覆盖专业编码,降低预期,覆盖 10%?20%?再到 30%? 已经是一个不错的成就。
低代码真正可以提效不仅在于它的形式(可视化),更在于它的生态。以前端界面搭建为例,背后开箱即用的组件、素材、模板、应用,才是它的快捷之道。
在我看来,低代码实际上并不是一个新技术,近年来火爆,更像是为了迎合资本的炒作而稍微具象化的概念。
而今天,真正的’降本增效‘的大刀砍下来,又有多少’降本增效‘的低代码活下来了呢?
质量管理的泡沫
2021 年四月,我开始优化前端开发质量管理,设计的开发流程如下:
开发环境:
- 即时反馈:通过 IDE 或者构建程序即时对问题进行反馈。
- 入库前检查:这里可以对变动的源代码进行统一格式化,代码规范检查、单元测试。如果检查失败则无法提交。
集成环境:
- 服务端检查:聪明的开发者可能绕过开发环境本地检查,在集成环境我们可以利用 Gerrit + Jenkins 来执行检查。如果验证失败,该提交会被拒绝入库。
- CodeReview:CodeReview 是最后一道防线,主要用于验证机器无法检验的设计问题。
- 自动化部署:只有服务端检查和 CodeReview 都通过才能提交到仓库
- 测试环境:即时部署,关闭安全检查、开启调试方便诊断问题
- 生产环境:授权部署
生产环境:
前端应用在客户端中运行,我们通常需要通过各种手段来监控和上报应用的状态,以便更快地定位和解决客户问题。
原则一:我认为“自动化才是秩序”:
文档通常都会被束之高阁,因此单靠文档很难形成约束力。尤其在迭代频繁、人员构造不稳定的情况。规范自动化、配合有效的管理才是行之有效的解决办法。
- 规范自动化。能够交给机器去执行的,都应该交给机器去处理, 最大程度降低开发者的心智负担、犯错率。可以分为以下几个方面:
- 语言层面:类型检查,比如
Typescript
。严格的 Typescript 可以让开发者少犯很多错误。智能提示对开发效率也有很大提升。 - 风格层面:统一的代码格式化风格。例如
Prettier
。 - 规范层面:一些代码规范、最佳实践、反模式。可以遵循社区的流行规范, 例如
JavaScript Standard
- 架构层面:项目的组织、设计、关联、流程。可以通过脚手架、规范文档、自定义 ESLint 规则。
- 语言层面:类型检查,比如
- 管理和文化: 机器还是有局限性,更深层次的检查还是需要人工进行。比如单元测试、CodeReview。这往往需要管理来驱动、团队文化来支撑。这是我们后面需要走的路。
原则二:不要造轮子
我们不打算造轮子,建立自己的代码规范。社区上有很多流行的方案,它们是集体智慧的结晶,也最能体现行业的最佳实践:
没必要自己去定义规则,因为最终它都会被废弃,我们根本没有那么多精力去维护。
实现
企业通知 Code Review
我们这套代码质量管理体系,主要基于以下技术来实现:
- Jenkins: 运行代码检查、构建、通知等任务
- Gerrit:以 Commit 为粒度的 CodeReview 工具
- wkfe-standard: 我们自己实现渐进式代码检查 CLI
如果你想了解这方面的细节,可以查看以下文档:
我推崇的自动化就是秩序目的就是让机器来取代人对代码进行检查。然而它只是仅仅保证底线。
人工 CodeReview 的重要性不能被忽略,毕竟很多事情机器是做不了的。
为了推行 CodeReview,我们曾自上而下推行了 CCC(简洁代码认证) 运动,开发者可以提交代码让专家团队来 Code Review,一共三轮,全部通过可以获得证书,该证书可以成为绩效和晋升的加分项;除此之外还有代码规范考试…
然而,这场运动仅仅持续了几个月,随着公司组织架构的优化、这些事情就不再被重视。
不管是多么完善的规范、工作流,人才是最重要的一环,到最后其实是人的管理
DDD / 中台的泡沫
近年来,后端微服务、中台化等概念火热,DDD 也随之而起。
上图的 DDD Google 趋势图,一定程度可以反映国内 DDD 热度的现实情况:
- 在 14 年左右,微服务的概念开始被各方关注,我们可以看到这年 DDD 的搜索热度有明显的上升趋势
- 2015 年,马某带领阿里巴巴集团的高管,去芬兰的赫尔辛基对一家名叫 supercell 的游戏公司进行商务拜访,中台之风随着而起,接下来的一两年里,DDD 的搜索热度达到了顶峰。
- 2021 ~ 2022 年,口罩期间,很多公司业务几乎停摆,这是一个’内修‘的好时机。很多公司在这个阶段进行了业务的 DDD 重构,比较典型的代表是去哪儿(业务瘦身 42%+效率提升 50% :去哪儿网业务重构 DDD 落地实践)。
上文提到,我们在 2021 年底也进行了一次轰轰烈烈的 DDD 重构战役,完全推翻现有的项目,重新梳理业务、重新设计、重新编码。
重构需要投入了大量的资源,基本公司 1 / 3 的研发资源都投入在里面了,这还不包括前期 DDD 的各种预研和培训成本。
在现在看来,这些举措都是非常激进的。而价值呢?现在还不’好说‘(很难量化)
DDD 落地难
其实既然开始了 DDD 重构, 就说明我们已经知道 ’怎么做 DDD‘ 了,在重构之前,我们已经有了接近一年的各种学习和铺垫,且在部分中台项目进行了实践。
但我至今还是觉得 DDD 很难落地,且不说它有较高的学习成本,就算是已落地的项目我们都很难保证它的连续性(坚持并贯彻初衷、规范、流程),烂尾的概率比较高。
为了降低开发者对 DDD 的上手门槛,我们也进行了一些探索。
低代码 + DDD?
可视化领域建模
2022 下半年,我们开始了 ’DDD 可视化建模‘ 的探索之路,如上图所示。
这个平台的核心理念和方法论来源于我们过去几年对 DDD 的实践经验,涵盖了需求资料的管理、产品愿景的说明、统一语言、业务流程图、领域模型/查询模型/领域服务的绘制(基于 CQRS),数据建模(ER)、对象结构映射(Mapper)等多种功能,覆盖了 DDD 的整个研发流程。
同时它也是一个知识管理平台,我们希望在这里聚合业务开发所需要的各种知识,包括原始需求资料、统一语言、领域知识、领域建模的结果。让项目的二开、新团队成员可以更快地入手。
最终,建模的结果通过“代码生成器”生成代码,真正实现领域驱动设计,而设计驱动编码。
很快我们会完全开源这套工具,可以关注我的后续文章。
DDD 泡沫
即使我们有’低代码‘工具 + 代码自动生成的加持,实现了领域驱动设计、设计驱动编码,结果依旧是虎头蛇尾,阻止不了 DDD 泡沫的破裂。
我也思考了很多原因,为什么我们没有’成功‘?
- DDD 难?学习曲线高
- 参与的人数少,DDD 受限在后端开发圈子里面,其他角色很少参与进来,违背了 DDD 的初衷
- 重术而轻道。DDD 涵括了战略设计和战术设计,如果战略设计是’道‘、战术设计就是’术‘,大部分开发者仅仅着眼于术,具体来说他们更关注编码,思维并没有转变,传统数据建模思维根深蒂固
- 中台的倒台,热潮的退去
扩展阅读:
一些零碎的事
过去三年还做了不少事情,限于篇幅,就不展开了:
- 前端容器化部署,CI/CD 流程的优化。详见:使用 Docker 实现前端应用的标准化构建、部署和运行
- 微前端升级。详见:微前端的落地和治理实战、管理端开发框架
- 管理端组件库。详见:如何实现支持跨 Vue 2/3 的组件库、前端如何破解 CRUD 的循环
过去三年经历时间轴:
- 2020 年 7 月,换了公司,开始接手真正迁移中的 Taro 项目
- 2020 年 10 月,Taro 2.x 小程序正式上线
- 2020 年 10 月 ~ 11 月 优化代码质量管理体系,引入开发规范、Gerrit Code Review 流程
- 2020 年 12 月 ~ 2021 年 4 月,业务开发
- 2021 年 1 月 博客停更
- 2021 年 5 月 Taro 3.x 升级
- 2021 年 7 月 ~ 10 月 前端低代码平台开发
- 2021 年 11 月 ~ 2022 年 5 月, DDD 大规模重构,C 端项目重构、国际化改造
- 2022 年 6 月 ~ 2022 年 11 月,B 端技术升级,涉及容器化改造、微前端升级、组件库开发等
- 2022 年 12 月~ 2023 年 4 月,可视化 DDD 开发平台开发
- 2023 年 5 月 ~ 至今。业务开发,重新开始博客更新
总结
我们都有美好的愿望
重构了又重构,技术的债务还是高城不下
推翻了再推翻,我们竟然是为了‘复用’?
降本增效的大刀砍来
泡沫破碎,回归到了现实
潮水退去,剩下一些裸泳的人
我又走到了人生的十字路口,继续苟着,还是换个方向?