重构这段烂代码,差点把我整凌乱了...

这篇具有很好参考价值的文章主要介绍了重构这段烂代码,差点把我整凌乱了...。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

🍀注重实效,不要靠巧合编程。
🍀在构造一个对象的过程中,应避免依赖对象已经设置的field来继续给对象的其他field赋值,而应该基于原始对象的field去判断。

 

先看这段代码,烂不烂,你可以品一下,多半味道不怎么好。

 1 try {
 2     final ResponseDTO responseDTO = bindCardService.bindCard(bindCardReqDTO);
 3 
 4     if (ObjectUtil.isNotNull(responseDTO)) {
 5         // 变更流水、绑卡记录状态->待认证
 6         bankCardFlow.setRemark(responseDTO.getReturnMsg());
 7         bankCardFlow.setStatus(StatusEnum.UNAUTH.getCode());
 8         bankCardFlow.setUpdateTime(updateTime);
 9 
10         bankCard.setStatus(StatusEnum.UNAUTH.getCode());
11         bankCard.setUpdateTime(updateTime);
12 
13         payMerchantBankCardManager.updateById(bankCard);
14         payMerchantBankCardFlowManager.updateById(bankCardFlow);
15     }
16     return Result.success();
17 } catch (Exception e) {
18     log.error("亿联-绑卡失败-异常:", e);
19     if (e instanceof YiLianBizException) {
20         bankCardFlow.setRemark(e.getMessage());
21     } else {
22         bankCardFlow.setRemark("出现异常-绑卡失败");
23     }
24     bankCardFlow.setUpdateTime(updateTime);
25     bankCard.setUpdateTime(updateTime);
26     if (bankCardFlow.getRemark().contains(YiLianConstant.TRADE_RESULT_UNKNOWN)) {
27         bankCardFlow.setStatus(StatusEnum.UNAUTH.getCode());
28         bankCard.setStatus(StatusEnum.UNAUTH.getCode());
29         payMerchantBankCardManager.updateById(bankCard);
30         payMerchantBankCardFlowManager.updateById(bankCardFlow);
31         return Result.success();
32     } else {
33         bankCardFlow.setStatus(StatusEnum.FAIL.getCode());
34         bankCard.setStatus(StatusEnum.FAIL.getCode());
35         payMerchantBankCardManager.updateById(bankCard);
36         payMerchantBankCardFlowManager.updateById(bankCardFlow);
37         return Result.err("亿联-绑卡失败,请重新绑卡");
38     }
39 }

 

在不改变业务逻辑的基础上,我重构这段代码,如下。将单表update操作做了封装,这里直接调用封装好的方法,同时增加状态锁控制。不过,一个点竟把我绕进去了。暂且标记TODO:“ 这里为什么判断bankCardFlow.getRemark()? ---逻辑被我改坏了?”。

 1 try {
 2     final ResponseDTO responseDTO = bindCardService.bindCard(bindCardReqDTO);
 3 
 4     if (ObjectUtil.isNotNull(responseDTO)) {
 5         // 变更流水、绑卡记录状态->待认证
 6         payMerchantBankCardManager.updateStateTo(bankCard, StatusEnum.UNAUTH, StatusEnum.INIT);
 7         payMerchantBankCardFlowManager.updateStateTo(bankCardFlow, StatusEnum.UNAUTH, StatusEnum.INIT, responseDTO.getReturnMsg());
 8     }
 9     return Result.success();
10 } catch (Exception e) {
11     String msg;
12     if (e instanceof YiLianBizException) {
13         log.error("亿联-绑卡失败:{}", e.getMessage());
14         msg = e.getMessage();
15     } else {
16         log.error("亿联-绑卡失败-异常:", e);
17         msg = "出现异常-绑卡失败" + ExceptionUtils.getMessage(e);
18     }
19     //TODO: 这里为什么判断bankCardFlow.getRemark()? ---逻辑被我改坏了?
20     if (bankCardFlow.getRemark().contains(YiLianConstant.TRADE_RESULT_UNKNOWN)) {
21         payMerchantBankCardManager.updateStateTo(bankCard, StatusEnum.UNAUTH, StatusEnum.INIT);
22         payMerchantBankCardFlowManager.updateStateTo(bankCardFlow, StatusEnum.UNAUTH, StatusEnum.INIT, msg);
23         return Result.success();
24     } else {
25         payMerchantBankCardManager.updateStateTo(bankCard, StatusEnum.FAIL, StatusEnum.INIT);
26         payMerchantBankCardFlowManager.updateStateTo(bankCardFlow, StatusEnum.FAIL, StatusEnum.INIT, msg);
27         return Result.err("亿联-绑卡失败,请重新绑卡");
28     }
29 }

 
隔了一天,我回头再review这段代码,跟前面的版本进行compare,终于看明白了。聪明的你,看出来破绽了吧? -------我差点犯了个错误呀,赶紧修正,把 bankCardFlow.getRemark().contains(YiLianConstant.TRADE_RESULT_UNKNOWN) 中的 bankCardFlow.getRemark() 改成 msg 变量。

 

这个案例涉及到我们在开发中需要注意的一个小细节。

在构造对象的过程中,通常应避免依赖对象已经设置的字段进行判断并继续给对象的其他字段赋值。相反,应该基于原始对象的字段进行判断。
【反例】下面if判断中使用了order#payType:

Order order = new Order();
...
order.setPayType(payRequest.getPayType());
...
if ("BANKCARD".contentEquals(order.getPayType())) {
    order.setBankCardNo(payRequest.getBankCardNo();
    order.setBankName(payRequest.getBankName());
} else if ("ALIPAY".contentEquals(order.getPayType())) {
    order.setAliAccount(payRequest.getAliUserId());
    ...

【正例】把if判断条件改为原始对象(入参或读库或调用其他接口得到的对象)payRequest#payType:

Order order = new Order();
...
order.setPayType(payRequest.getPayType());
...
if ("BANKCARD".contentEquals(payRequest.getPayType())) {
    order.setBankCardNo(payRequest.getBankCardNo();
    order.setBankName(payRequest.getBankName());
} else if ("ALIPAY".contentEquals(payRequest.getPayType())) {
    order.setAliAccount(payRequest.getAliUserId());
    ...

 

 

 

有同学会反问,这有什么区别呢?

有的。

其一,在设置order对象的payType字段之后,该字段的值可能会发生变化,导致后续的判断结果不准确。

其二,当Order的属性较多时,构造Order对象的代码行会比较多。如果按照【反例】做的话,代码维护过程中一旦出现先get后set的情况,将会导致程序bug。——不可能出现这样的事情?!别说不可能,只能说你还没有遇到。

细微处见成色!我们在日常编码中,要注重细节,注重实效,不要靠巧合编程。拿本案来说,就是要按【正例】做,不给bug留空子。

 

 


后记-补充

 【反例2】下面的代码同样不OK。

totalDto.setYunFeiTotal(afterCell.getNumericCellValue())
        .setTotal(-totalDto.getYunFeiTotal());

 

【正例2】

var val = afterCell.getNumericCellValue();
totalDto.setYunFeiTotal(val)
        .setTotal(-val);

或改为

totalDto.setYunFeiTotal(afterCell.getNumericCellValue())
        .setTotal(-afterCell.getNumericCellValue());

 

 

 

The End.文章来源地址https://www.toymoban.com/news/detail-747720.html

到了这里,关于重构这段烂代码,差点把我整凌乱了...的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 代码重构的时机与方法

    🐱 个人主页: 不叫猫先生 ,公众号: 前端舵手 🙋‍♂️ 作者简介:2022年度博客之星前端领域TOP 2,前端领域优质作者、阿里云专家博主,专注于前端各领域技术,共同学习共同进步,一起加油呀! 💫优质专栏: vue3+vite+typeScript从入门到实践 📢 资料领取:前端进阶资料

    2024年02月16日
    浏览(29)
  • 换了vue3+alova后,老板被我整笑了

    老板又来了BT的需求😳 我们公司最近开发一款todo管理产品,vue3+axios,事情是这样的。 老板:我们的产品测试版我试用了,整体实现的不错,不过…… 我:😨😨😨 老板:体验上有待优化一下,比如……todo列表页翻页的时候能不能瞬间展示数据?添加和编辑todo的时候可不

    2024年02月04日
    浏览(41)
  • 编程之道:【代码重构】提升代码质量的关键一步

    在软件开发的旅程中,不仅仅是代码的编写,还包括了代码的维护和改进。代码重构是其中的一个重要环节,它强调的是改进代码的内部结构,使其更容易理解、维护和扩展。本文将探讨代码重构对于改进代码质量的重要性。 代码重构是什么? 代码重构是一种在不改变软件

    2024年02月11日
    浏览(26)
  • 重构改善既有代码的设计-学习(一):封装

              一些记录性结构(例如hash、map、hashmap、dictionary等),一条记录上持有什么字段往往不够直观。如果其使用范围比较宽,这个问题往往会造成许多困扰。所以,记录性结构应该被封装成为一个类。         例如:         应该被重构为:           我们通常鼓

    2024年01月21日
    浏览(26)
  • 程序员如何高质量重构代码?

    有道无术,术尚可求也,有术无道止于术。你好,我是程序员雪球,今天和你聊聊程序员重构代码那些事。   程序员重构代码的重要性不言而喻,但如何进行有效的重构呢?下面是一些建议和指导。 为什么要重构? 重构是提高代码质量和可维护性的重要手段,旨在在不改变

    2024年02月15日
    浏览(47)
  • 【Java设计模式 规范与重构】 二 重构的保障:单元测试,以及如何提高代码可测试性

    其实之前的工作中强调过很多次自己做测试的重要性,例如讲单元测试的: 【C#编程最佳实践 一】单元测试实践 ,讲单元测试规范的 【阿里巴巴Java编程规范学习 四】Java质量安全规约 ,讲接口测试的: 【C#编程最佳实践 十三】接口测试实践 ,这里旧事重提就不再详细展开

    2023年04月25日
    浏览(37)
  • 编程之道:【代码重构】消除异味和坏味道,提升代码质量

    在软件开发中,有时会遇到一些让人不爽的情况,代码也不例外。这些情况被称为“代码异味”或“坏味道”。它们可能表明代码存在问题,需要进行重构以提升质量和可维护性。本文将介绍代码异味和坏味道是什么,以及如何识别和解决它们。 代码异味和坏味道是什么?

    2024年02月10日
    浏览(31)
  • Visual Assist 代码辅助检查和重构

    Visual Assist填补了Microsoft Visual Studio中的空白。它帮助开发人员更快更容易地编写代码。作为世界各地C++和C#开发人员所依赖的关键生产力工具,您使用的软件很可能是在Visual Assist的帮助下编写的。无论是比Microsoft Visual Studio中内置的导航更好,还是重构、代码生成等等,Visu

    2024年02月04日
    浏览(21)
  • 实际业务中使用策略模式对代码进行重构

    最近在负责公司一个语音的微服务模块优化,这个模块主要的业务是:1.天猫精灵、小度、若琪、小京鱼、小爱同学、思必驰这些第三方音响对我们的用户进行oauth2/JWT授权; 2.这些第三方音响服务调用我们的设备发现接口对公司的设备信息在第三方平台进行一个存储;3.第三

    2024年02月05日
    浏览(26)
  • C#代码重构的几个典型案例

    前段时间小编检查同事代码,发现居然写的太复杂看不太懂,代码命名不规范,重复冗长代码一堆,这时候就可以通过重构来改进代码的质量。代码重构是提高代码质量和可维护性的关键过程,它旨在通过优化代码结构和设计来提高代码的可读性、可理解性和可扩展性。本文

    2024年02月16日
    浏览(26)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包