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

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

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


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交付统一工作台,让交付的过程、节奏数字化管控,可度量可预测;
  • 更加关键的是,我们在交付研发工作中,努力在建团队、建机制,沉淀客户数字化建设阶段的过程资产,包括但不限于架构文档、系统分析&详设文档、接口文档、可维护的代码&测试用例等,让客户的数字化建设“离开我们,还能行!”


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

相关文章
|
7月前
|
前端开发 JavaScript 测试技术
探索现代前端工程化工具与流程:提升开发效率和项目质量
探索现代前端工程化工具与流程:提升开发效率和项目质量
探索现代前端工程化工具与流程:提升开发效率和项目质量
|
7月前
|
资源调度 前端开发 测试技术
前端工程化实践:从零搭建现代化项目构建流程
【4月更文挑战第6天】本文介绍了前端工程化的概念和重要性,包括模块化、自动化、规范化和CI/CD。接着,讨论了选择合适的工具链,如包管理器、构建工具和测试框架。然后,详细阐述了如何从零开始搭建一个基于React的现代化项目构建流程,涉及初始化、代码规范、测试、CSS处理、代码分割和CI/CD配置。最后,提到了持续优化与迭代的方向,如性能优化、类型检查和微前端。通过这样的实践,开发者可以提升开发效率和代码质量,为项目长远发展奠定基础。
338 0
|
7月前
|
监控 前端开发 测试技术
前端研发流程的深入解析:从构思到交付
前端研发流程的深入解析:从构思到交付
159 0
|
7月前
|
自然语言处理 前端开发 测试技术
前端工程化最佳实践:项目结构、代码规范和文档管理
前端工程化最佳实践:项目结构、代码规范和文档管理
|
5月前
codereview开发问题之降低代码复杂度问题如何解决
codereview开发问题之降低代码复杂度问题如何解决
|
2月前
|
前端开发 JavaScript 测试技术
前端研发链路之代码规范
大家好,我是徐徐。本文将探讨前端研发链路中的代码规范,包括业界流行规范、CSS命名规范和相关工具。通过保持代码整洁和一致性,不仅能提高团队协作效率,还能减少错误,提升开发质量。文中详细对比了几种常见的代码规范和工具,如 Airbnb Style Guide、BEM、Eslint 和 Prettier,并展望了未来代码规范的发展趋势。希望对大家有所帮助。
100 1
前端研发链路之代码规范
|
4月前
|
前端开发 JavaScript 测试技术
构建与部署全栈JavaScript应用:从构思到上线的完整指南
【8月更文挑战第9天】构建和部署一个全栈JavaScript应用是一个复杂但充满挑战的过程。从需求分析到项目上线,每一步都需要精心策划和严格执行。通过本文的指南,希望能帮助你更好地理解和掌握全栈JavaScript应用的开发流程,从而打造出高性能、高可用、易维护的应用。
|
4月前
|
持续交付 C# 敏捷开发
“敏捷之道:揭秘WPF项目中的快速迭代与持续交付——从需求管理到自动化测试,打造高效开发流程的全方位指南”
【8月更文挑战第31天】敏捷开发是一种注重快速迭代和持续交付的软件开发方法,通过短周期开发提高产品质量并快速响应变化。本文通过问题解答形式,探讨在Windows Presentation Foundation(WPF)项目中应用敏捷开发的最佳实践,涵盖需求管理、版本控制、自动化测试及持续集成等方面,并通过具体示例代码展示其实施过程,帮助团队提升代码质量和开发效率。
77 0
|
7月前
|
敏捷开发 测试技术 持续交付
深入探索软件测试自动化:框架与实践
在快速演进的软件行业中,测试自动化已成为确保产品质量和加快上市速度的关键因素。本文将深入分析测试自动化框架的构建要点,探讨其在实际应用中的效益,以及实施过程中可能面临的挑战。通过对比手动测试与自动化测试的优势与局限,本文旨在为读者提供一套系统化的测试自动化实践指南,以支持更高效、可靠的软件开发周期。
|
运维 前端开发 jenkins
前端自动化集成部署交付实践
随着前后端分离应用模式的推广,前端项目可独立部署维护上线,不再仅仅将前端开发后打包的文件直接丢到一个文件目录下就完事大吉了,现在对前端来说也需要了解运维的相关知识,本文旨在介绍一些相关的运维概念以及一些前端运维的实践。
339 0