作者 | 肖迪(墨诩)

来源 | 阿里开拓者"大众年夜众号

序言

优酷CRP系统-内容采购版权管理系统,是个存在10年的老系统,技能框架上比较老旧;再加上”人来人往“,一定存在很多”不合理但是能跑“和”不敢改,以是ifelse“等等经典代码,一共81w行java代码,17w的jsp代码。
我在今年全面接手CRP-财务部分,整体目标便是全面推进CRP财务的业财一体进程。
而这些遗留的技能问题都是推进进程的寻衅,以是CRP财务本财年的技能主题便是“老系统重构”。

JSP求最小公倍数上线十年81万行Java代码的老体系若何重构 Docker

根据以往的事情履历,面对这样的系统,大开大合的重构改版,带来的每每是更加灾害性的”业务不可用“;以是我们的策略,还是要秉着业务优先的原则,跟随业务新需求来逐步重构。
但无论产品还是研发心中都要有同一张大图,我们终极要做成什么样子。
然后根据大图划清各个业务模块的边界,在担保不会影响其他模块的运行的条件下,进行重构。

81w行java代码中,实在大部分都是废代码,比如:功能和做事还在但是没有人利用;数据都已经迁移到其他系统,下贱也不在实际利用,但依赖还在;有很多job还在运行,但并没有实际的数据产出利用方。
之前重构的时候跟组里同学开玩笑说“如果随机注释掉一个service中是所有方法实现,系统大概率还是work的”,虽然我们不会这样做,但可能是真的。
对付这样的系统,重构的策略如果是重新梳理所有做事的利用情形,无疑是本钱特殊高的,roi很低。
以是该当按需重构和迁移,并担保下贱依赖方的不须要做任何改动。

本篇文章会以个中一个模块“付款”来作为示例,缘故原由有二:

一、本财年付款的改版业务述求比较高,这个S的重构进程较其他模块更快一些;

二、想表达的主题更专注在代码重构方向。
付款作为全体优酷运营中比较末端的商业行为,在系统上对付付款依赖的下贱系统和模块较少。
如果是写“条约迁移和改造”,会更偏架构重构和老系统、数据的迁移方案。

付款模块一共涉及大概3w行旁边的代码,首先担保下贱依赖的接口都不变,还在原有工程做事,并且将老代码迁移到新的工程下。
是否迁移工程取决于与迁移的ROI,我们的老工程的前端是用jsp实现的,现在要做前后端分离,以是老代码迁移到新的工程下。

付款

重构的第一原则因此业务为中央,不要为了重构而重构。
先来理解一下付款的业务和业务的痛点。

付款要办理的业务问题

付款紧张办理俩个问题:1、0资损;2、流程效率

我通过MECE的从下而上的归纳整理后,谨严判断想法建议的“最小公倍数”的方法,对付款进行梳理,先理解一下付款在做一件什么事,以及如何完成目标?

给谁付:收款人是谁?是否有财务或者法务上的风险?以及须要验证对方供应的发票为谁付:决定了付款的本钱归属,归属到节目、部门或者财务口径的入账科目上付多少钱:是否存在应收款和搪塞款可以互抵的情形?付款依据是什么?税费如何打算?怎么付:通过什么办法支付,先票后款还是先款后票,是否支持预约付款?能不能付:根据不同业务场景以及金额,流转到不同的审批人进行审批。

将这些要办理的业务问题向上抽象总结,付款要想做到

0资损:信息校验:很多根本信息的校验,最基本的不能付错人风险拦截:包括风险供应商拦截和风险金额的拦截金额精准:依据条约、账单、项目等打算出搪塞金额,然后进行对抵和税费打算(如有)金额依据状态同等:既然金额的精准决定了最多付多少钱,就要担保金额依据与付款单的状态同等性提高流程效率:自动凭据入账多种付款办法的支持快捷的流程审批

到这里该当可以看出来,付款不是一个繁芜业务流程的模块,它的核心述求是“稳定”与“可扩展”。
从这个季度的需求也可以验证这点

付款的技能痛点

代码臃肿,扩展性低

付款有个特点,没有很繁芜的业务流程,但是涉及到资金,在付款之前须要做很多的金额打算和风险校验。
而且其余一个特点,付款作为一个工具性子的模块,会接入很多业务方。
不同的业务,在金额打算、风险校验等流程上基本同等,但实际接入实现的时候,会有或多或少的差别(比如,付款金额的依据上,主客和OTT会有不同类型的账单)。
可以看出付款这部分对付复用性、扩展性哀求是比较高的。
现在要接入OTT的付款,我们先来看一下如果连续在老代码长进级,会有哪些问题。

@Override @Transactional(rollbackFor = Exception.class,transactionManager = "transactionManager2") public Payment submitPayment(PaymentDto paymentDto, User user) { 只保留能解释问题的关键代码或者注释,省去前全体方法600行旁边 payment工具初始化代码 ...省去60行代码... Integer r = paymentDao.insertPayment(paymentDto); payment付款依赖工具初始化代码 //保存关联节目 playComponent.dealPaymentPlay(paymentDto.getId(), ListUtils.emptyIfNull(paymentDto.getPaymentPlayDtoList()), user); //保存文件 appendixComponent.dealFile(paymentDto.getId(), ListUtils.emptyIfNull(paymentDto.getFileDtoList()), user); //保存账单 paymentAssociatedBillComponent.dealBill(paymentDto.getId(), ListUtils.emptyIfNull(paymentDto.getBillDtoList()).stream().map(AssociatedBillDto::getBillId).collect(Collectors.toList())); //保存任务人和其他操作人 comPermissionComponent.saveComPermission(paymentDto, "ALL"); 第一步做金额和风险校验,为大略只保留注释,省去实当代码 //1.校验重复提交 ...省去5行代码... //2.提交前校验 ...省去20行代码... //3.校验账单金额&&所属公司 ...省去5行代码... //4.校验娱乐宝账号 ...省去1行代码... //5.校验付款条件 checkPayCondition(payment); //6.校验节目金额 if (paymentComponent.needPaymentToPlay(payment.getType())) { checkPaymentSubject(payment); } 校验过程中混入payment工具初始化代码 CrpContract contract = crpContractDao.getContractById(payment.getContractId()); Integer operationFlow = contract.getOperationFlow(); payment.setContractOperationFlow(operationFlow); //7.校验本次申请金额是否超过预期 ....省去40行代码... //8.仅版权采购条约支持预约付款 if (){ throw new RuntimeException("仅版权采购条约支持预约付款!
"); } //8.校验预约付款不能选择先款后票 if (){ throw new RuntimeException("预约付款仅支持先收票后付款!
"); } //9.版权采购&&收款账户国家为CN&&签约币种为RMB 才可以利用预约付款 ...省去10行代码... payment工具初始化代码 payment.setApplyDate(new Date()); ...省去40行代码... 多了一次没有必要的数据库update paymentDao.updatePayment(payment); payment工具初始化代码 String actualApplyWorkNo = payment.getActualApplyWorkNo(); ...省去10行代码... paymentDao.updatePayment(payment); //异步提交审批流 BpmsDto bpmsDto = new BpmsDto(); ...省去10行代码... return payment; } private xxx(){}

比较范例的“流水账”代码,最直不雅观会导致的问题便是掩护困难,比如想查一个字段禁绝确的bug,最差情形要通读600+代码(还有部分private方法)。
在升级的时候,最随意马虎想到的办法便是连续盖楼(比如代码中调用了俩次 paymentDao.updatePayment(payment),该当便是盖楼的时候,代码复制多了),从而使“泥丸”越滚越大。

剩余60%,完全内容请点击下方链接查看:

上线十年,81万行Java代码的老系统如何重构

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开拓者社区不拥有其著作权,亦不承担相应法律任务。
详细规则请查看《阿里云开拓者社区用户做事协议》和《阿里云开拓者社区知识产权保护指引》。
如果您创造本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将急速删除涉嫌侵权内容。