【组件开发实践】一段引发资损的代码重构-交付那些事

简介: 在支撑客户数字化转型的具体实施中经历的一段小插曲,引起了一些相关的思考,比如到底我们今天做的这些事情,有没有“技术含量”。

曾在一个数字化交付项目中和伙伴聊天,被问这么个问题:为什么现在这个项目中加个功能,要改动这么大,涉及到其他几个功能的改动,这是不是不合理,是不是技术方案有问题,是不是我们写代码的人能力不行...好家伙,我直呼好家伙,几个问题让身为码农多年的我无法回答,一时失语,陷入了沉思...


2021年8月的一天,某项目业务同学对上月涉及缴费业务场景的缴费记录进行人工对账,发现存在部分(几十笔)用户重复缴费。


项目组在问题被发现的第一时间启动应对,在通过一定措施止血的基础上,开始对疑似问题代码进行分析。


先简单说一下该场景费用缴纳的大致实现逻辑:


  • 首先针对每位会员、基于其基本情况按周期生成待缴费用记录(fee_record);


  • 针对每条fee_record,会员自身、或会员所在组织管理员可发起缴纳:通过fee_record生成一笔交易(trade,当前只有支付宝缴纳渠道);


  • 基于生成的trade(有对应的外部交易号out_trade_no,在当前业务系统全局唯一。同时out_trade_no+当前业务支付宝注册伙伴号pid在支付宝侧全局唯一,并有对应的支付宝全局唯一内部交易号trade_no)


  • 基于fee_record创建后的交易,支付超时时间15mins,超时后交易自动关闭(无法支付),需要重新创建交易。


  • 针对一条fee_record记录开始缴纳时,将生成一条pay_result记录,用于跟踪关联的支付宝交易(的状态),因此每条fee_record记录可能(因为交易超时)会关联多条pay_result记录,但最终一定只有一条“缴纳成功的”pay_result记录。






整体来看,逻辑似乎并不复杂。但在本项目过程中:

  • 该功能在第一版交付上线时,为追赶工期,仓促上线,未经充分的方案设计和后续的测试验证;
  • 该功能上线后,在近一年左右的时间内,客户多次启动上线未果(业务原因);
  • 该项目历时1年多,研发团队几经变更,本功能涉及到的代码也是几易其手;


最终出现问题时,其中一坨代码长差不多这个样子:(有兴趣可以放大看看)











为什么要看这坨代码呢,因为当时出现重复缴费,从数据库记录看,最核心的原因就是,针对一笔待缴费fee_record记录,重复生成了多笔trade(对应多条pay_result记录),且均被用户支付。


首先简单说明一下我自己看到这段代码的感受:首先内心一定是抗拒的,一个200多行的方法,以这样一种形态摆在面前,(以前自己赶工的时候也不是没干过,但毕竟那是自己“亲生”的,而且往往找个机会就重构了,当然业务干不下去的另说),而且是已经交付终验的项目,真心不想去动它。


但当仔细看了这坨代码的逻辑后,还是决定动手重构,首先简单罗列一下这段代码的问题:

  • 大事务,这当然是今天交付项目中,@Transactional声明式事务滥用的常见状况,在这个项目中也不例外,一个注解框住,中间是n次远程调用+n次db交互;
  • 锁的问题:用了一个缓存锁,做过支付or金融的同学都清楚,这种锁其实严格等于没锁,一般仅用于弱防并发;
  • 数据更新判定问题:比如在新增or更新相关记录时,从来就没有做过检查判断,更不用提严格的事务中的带锁检查;
  • 更恐怖的是,如果这个方法远程调用成功(创建一笔交易),然后本地事务回滚后...


在这种代码面前,谈命名、谈抽象、谈注释、谈SOLID,其实都太苍白,只能先解核心的问题。


重构后的代码主体结构大概长这样(抽了一些方法):






这个重构从对原有代码的分析到着手编写,到基本的自测,花了差不多1周时间,而且很多看起来很不合理甚至丑陋的地方并没有动也不敢动。为了分析和给相关同学说明清楚,还提前花时间画了下面这张图。








废话基本上说完了,借这个事情,我想和大家严肃交流一下如下几个问题。(图穷匕见)


交付有没有技术含量


当然其实应该首先探讨下什么是“技术含量”,这个是个引战题,就不在这里过多探讨了,我更倾向于结合在阿里包括蚂蚁这些年的实践经历,来自己先做个简单的判断:因为主要涉及到的都是业务系统建设,所以大概“正相关”一下对应的技术实施难度


没有严格数据统计,讲讲自己这一年多来经历的交付项目的一些实际场景和感受。


以上面这个项目为例,在这个项目里面,涉及到该行业非常多的业务场景,从线下活动、到线上的直播会议、商城、收单支付、积分营销、结算账单、数据分析、统计报表等。相关的功能在当前项目中几乎完全定开,在里面我看到了之前在阿里内部非常多的业务场景的雏形。截止目前该项目移动app的平均日活跃用户20w左右,活动日峰值1000TPS,这已经是差不多几年前蚂蚁国际某重点业务的体量了。


这些场景如果要做好,或者往好了做,其实在厂内遇到的很多问题都要解,不论是产品方案、架构设计本身,还是涉及到相关非功能性分析设计,代码实现,质量保障,包括整体的技术风险应急体系等,都需要专业的来应对。


以上述问题代码为例,简单来讲,好像就是CRUD boyAPI girl做的一些事情,但实际上真的是这样的吗?其实要落地好这段代码相关功能,首先基本的业务流对应的信息流、资金流等起码要分析清楚,包括其业务场景所包含的各种随着时间发生的变化,比如缴费者与缴费对象账号之间的关系的变化以及背后的资金结算、资金归集等逻辑;为了严格防止或及时发现资损,理论上也应该做好各方之间的资金对账,包括账账、账证、账实等;基于业务场景,还应该设计好对应的业务链路上各领域的模型以及实体之间信息的转换逻辑,包括实体状态机的小心设计等,以及内外部关键服务中的幂等防并发设计;同时在完善好功能性设计、做好资损防控设计的同时,还需要考虑好随着客户业务发展带来的服务的可用性、稳定性、性能等非功能性指标,以及客户系统未来持续的可维护性和可扩展性...这些事情真的很简单吗?至少以往的经历(毒打)教会我的是,不简单


但实际上,当时在该项目上线这一功能的第一版(客户能在app上看到一个缴费按钮),其实就是合作ISV一前端一后端直接撸码3天赶工上线,“测试通过”。而这3天上线的代价,是截止目前的N轮代码的修改、测试、以及当前发生的资损。


所以我自己看到和所理解的是:


  1. 交付场景,尤其是今天基于B/G客户业务场景深度定制化的交付场景,本身是很有技术含量的;
  2. 我们自身在交付的过程中,受限于客观成本或代价(时间、金钱),没有按照“有技术含量的方式”来做;
  3. 在这些交付中,我们的交付过程包括过程产物(比如代码、方案文档等)本身也“不是很有技术含量”;
  4. 交付的结果,最终也“缺失了技术含量”;


所以,最终无论是我们内部个别声音、还是来自个别客户的声音是:交付工作不够有技术含量...


我们交付的是什么:是项目,是产品,还是服务


通常来讲,我们在交付场景交付的是一个个项目:立项、基于功能清单招投标、交付团队进场、迭代、项目初验、迭代收尾、项目终验...结款走人,最后可能加上一两年的项目维保。


从客户的视角,可能希望买的是一个“可用的产品”,就像买一栋期房或者定制化别墅,先看图纸、材料、工艺,满意就交点预付款,施工队进场施工,中间穿插一些过程验收,最终建成后验收,付尾款,客户入住。


但存在这样一些项目,有些客户渐渐意识到不对劲:为什么两年前买的“房子”,到今天可能就“住不了人”了,“要住人”得加钱,甚至“推倒重建”。强势一点的客户就开始发飙:我xxxxW买的“房子”,今天告诉我住不了人?不行,必须给我搞定,要不然我就搞定你。当然这纯属说笑(说笑?)...


但是作为身处其中的我,也一直在思考:到底我们为客户交付的是什么?现在阿里云适时提出了“做好服务”,笔者所在的研发组织落脚点也是“服务”,从传统的TO B行业来讲,其实关键也是讲“服务”。


谈到服务,我就想起了关于日本的一个段子(也不算段子):听说在日本去买鞋,只要一进鞋店试鞋,基本上也就会把鞋给买出来,主要原因是人家卖鞋的美女除了“品貌举止上佳”,还一直“跪式服务”不厌其烦捧着你那双充满味道的脚给你试鞋,试问但凡脸皮薄点、亦或是有点绅士情结,是不是好歹也要从这店里硬选出一双鞋?如果多试两下,让人家多跪了几次,到最后付钱出门走人,路上是不是还心怀愧疚:我真是不应该!让人家跪了这么久...


在传统的服务行业,“客户关系”意味着很多不可言说的涵义,但回到今天,云原生时代我们的数字化交付服务场景,试问我们真正期望带给客户的价值是什么?或者客户真正的期望是什么呢?


好了,扯了这么多,我想直接表达一下个人的理解:数字化交付工作,本质是要帮助我们的客户做好“数字化转型”这件事情,这件事情本身不是静态的,而是随着客户自身业务的变化而变化、发展而发展、壮大而壮大,不仅仅要满足客户的当下的数字化转型要求,也要满足客户未来持续的数字化建设诉求,因此不是“一个项目”、“一个产品”、“一锤子买卖”所能涵盖的,当然不排除有些交付项目,可能也是客户自身短期KPI导向的一锤子买卖,但那绝对不是常态、是不可持续发展的,因此也不应该是“怀揣梦想的技术人”所殷殷以盼、孜孜以求的机会。


所以,数字化转型交付,本身交付“服务”毋庸置疑。在交付过程中,我们不仅仅要搭建一些网站、实现一些app,更应该帮助客户构建起其数字化转型的基座,并能够让客户在这个基座上持续的去勾勒其数字化蓝图。如果一定要类比“一座房子”的交付,首先我们交付给客户的房子,除了面向当前“可住人”,还要面向未来“可持续住人”,当未来客户业务大变,需要整体“翻修”时,我们交付的“图纸”、“机制”、“工具”甚至“团队”还能够帮助到客户,这样带来的价值,才是可持续的,这样的数字化交付,才显得有“技术含量”!


我们在怎样做交付


在怎样做交付这件事情上,我们团队和兄弟团队一起已经持续在做一些深入的探索。回望过去,作为一名交付场景中的研发人员,我个人也有幸在不同项目中深入参与到研发实践的部分。



  • 首先我们努力在交付的方案分析设计层面,用DDD、SOLID等专业的架构方法论做指引,在成本可控的范围内打牢架构基线;
  • 其次我们高度依赖了支撑架构分析设计以及研发落地的云原生交付平台-GTS交付统一工作台,让交付的过程、节奏数字化管控,可度量可预测;
  • 更加关键的是,我们在交付研发工作中,努力在建团队、建机制,沉淀客户数字化建设阶段的过程资产,包括但不限于架构文档、系统分析&详设文档、接口文档、可维护的代码&测试用例等,让客户的数字化建设“离开我们,还能行!”


当然,我们还做了很多,但我总觉得,我们应该在一些很确定的地方和方向上,做得更多、做得更好、做得更扎实,让我们的客户在数字化转型的路上行稳致远,“让交付更有技术含量”!

相关文章
|
21天前
|
资源调度 前端开发 测试技术
前端工程化实践:从零搭建现代化项目构建流程
【4月更文挑战第6天】本文介绍了前端工程化的概念和重要性,包括模块化、自动化、规范化和CI/CD。接着,讨论了选择合适的工具链,如包管理器、构建工具和测试框架。然后,详细阐述了如何从零开始搭建一个基于React的现代化项目构建流程,涉及初始化、代码规范、测试、CSS处理、代码分割和CI/CD配置。最后,提到了持续优化与迭代的方向,如性能优化、类型检查和微前端。通过这样的实践,开发者可以提升开发效率和代码质量,为项目长远发展奠定基础。
27 0
|
4月前
|
前端开发 JavaScript 测试技术
探索现代前端工程化工具与流程:提升开发效率和项目质量
探索现代前端工程化工具与流程:提升开发效率和项目质量
探索现代前端工程化工具与流程:提升开发效率和项目质量
|
4月前
|
自然语言处理 前端开发 测试技术
前端工程化最佳实践:项目结构、代码规范和文档管理
前端工程化最佳实践:项目结构、代码规范和文档管理
|
26天前
|
测试技术 持续交付 API
深入理解自动化测试框架的设计原则与实践
【4月更文挑战第4天】 在软件开发的快速迭代中,自动化测试成为确保产品质量和加速交付过程的关键因素。本文将探讨自动化测试框架的设计原则及其在实际项目中的应用。通过分析不同测试场景下的需求,我们提出了一系列设计原则,旨在提高测试框架的灵活性、可维护性和扩展性。同时,文中还将分享几个成功案例,展示如何根据这些原则构建高效且可靠的自动化测试框架。
|
4月前
|
运维
你们的开发模式是敏捷的吗?
你们的开发模式是敏捷的吗?
|
8月前
|
敏捷开发 测试技术 项目管理
​ 敏捷开发和传统开发的区别?以及Scrum敏捷管理工具推荐
Leangoo领歌一款永久免费的专业敏捷研发管理工具,它覆盖了敏捷项目研发全流程,包括小型团队敏捷开发,规模化敏捷SAFe,Scrum of Scrums大规模敏捷。能够支持多种场景,如:敏捷研发管理、敏捷项目管理、工作流管理、轻量级项目群管理、任务管理等。
|
9月前
|
敏捷开发 数据可视化 测试技术
敏捷开发方法和工具:让你的团队更高效、更灵活
Leangoo领歌是一款永久免费的专业敏捷开发管理工具,也提供私有部署。国产软件,提供端到端敏捷研发管理解决方案,包括小型团队敏捷开发,规模化敏捷SAFe,Scrum of Scrums大规模敏捷.
|
10月前
|
数据可视化 算法 前端开发
一文吃透低代码平台源代码交付的重要性(避坑指南)
一文吃透低代码平台源代码交付的重要性(避坑指南)
204 0
|
12月前
|
运维 前端开发 jenkins
前端自动化集成部署交付实践
随着前后端分离应用模式的推广,前端项目可独立部署维护上线,不再仅仅将前端开发后打包的文件直接丢到一个文件目录下就完事大吉了,现在对前端来说也需要了解运维的相关知识,本文旨在介绍一些相关的运维概念以及一些前端运维的实践。
284 0
|
敏捷开发 消息中间件 小程序
谈谈软件开发模式:瀑布与敏捷
谈谈软件开发模式:瀑布与敏捷