草庐IT

两点之间直线最短,你写的是代码,我写的是艺术

buguge - Keep it simple,stupid 2023-04-19 原文

随着需求迭代,团队代码量逐渐增多,熵增崭露头角。临近月底,我打开部分程序,再做一次代码走查。

 

✅ 两点之间直线最短

我在做代码走查的时候,发现一个service方法里有这么一段代码

    List<PlatOrder> platOrderList = platOrderService.selectByOrderIds(Lists.newArrayList(bankOrder.getOrderId()));
    if (CollectionUtils.isEmpty(platOrderList)) {
        throw BizException.build("服务商未落单");
    }

    paymentReq.setOrigTransNo(platOrderList.get(0).getMerOrderId());

 

先说一下PlatOrder对应的数据表plat_order,plat_order是平台付款订单表,orderId是平台订单号,字段上有唯一索引。
我看这段逻辑,直觉是为什么调用 PlatOrderService#selectByOrderIds 方法获取一个列表,然后再取第一个元素呢? 绕这么一个弯儿干啥,殊不知两点之间直线最短。我赶紧翻一下 PlatOrderService 的方法列表。 发现果然有另一个方法 selectByOrderId 。那么,这里调用 selectByOrderId ,像下面这样,是不是更优雅?

    PlatOrder platOrder = platOrderService.selectByOrderId(bankOrder.getOrderId());
    Assert.notNull(platOrder, "服务商未落单");

    paymentReq.setOrigTransNo(platOrder.getMerOrderId());

 

 

✅ 世上无易事,用心求精进

PlatOrderService 是基于 plat_order表的CRUD操作的service接口类。先说一下plat_order表,plat_order是平台付款订单表,orderId是平台订单号,字段上有唯一索引。
我在做代码走查的时候,发现 PlatOrderService 里有这么一个方法

public interface PlatOrderService {
    
    /**
     * 根据订单流水号查询单条平台订单记录
     * @param orderId
     * @return
     */
    List<PlatOrder> selecPlatOrderByOrderId(String orderId);
}

 

为什么会有这么一个方法呢?据我分析:①是当事人不清楚orderId的作用;②当事人迷糊、马虎,未加思考未作了解就写出来的;③当事人参考其他service如法炮制、信手拈来;④年久失修。

我不能再容忍这样的方法继续被使用。
因此,改成这样:

public interface PlatOrderService {
    
    /**
     * 根据订单流水号查询单条平台订单记录
     * @param orderId
     * @return
     */
    default PlatOrder selectByOrderId(String orderId){
        List<PlatOrder> list = selecPlatOrderByOrderId(orderId);
        if (CollectionUtils.isNotEmpty(list)) return list.get(0);
        return null;
    }
    
    /**
     * 根据订单流水号查询单条平台订单记录
     * 不要再调用这个方法了,请使用{@link #selectByOrderId(String)}
     * @param orderId
     * @return
     */
    @Deprecated
    List<PlatOrder> selecPlatOrderByOrderId(String orderId);
}

 

某天深夜,我突然一想,我的正确姿势,应该是直接删掉这个方法,斩草要除根。上班后,立即行动。快刀斩乱麻,相关调用一并改掉。

public interface PlatOrderService {
    
    /**
     * 根据订单流水号查询单条平台订单记录
     * @param orderId
     * @return
     */
    PlatOrder selectByOrderId(String orderId);
}

 

✅ 使用封装,彻底斩草除根

在请求外部三方通道付款完成后,外部三方通道系统会主动回调我方接口。我方程序里对于每个三方通道,都有一个对应的通道处理类。

几天前系统交易量增大,系统处理能力明显下降。经排查,发现一个通道处理类里,在使用 mybatisplus 的 Wrapper 根据单号获取订单记录时,由于单号字段类型不匹配,导致单号上的索引失效,数据库在执行sql时走了全表扫描,进而产生蝴蝶效应,拖垮整个系统。

我们立即修复这段代码。我意识到,其他通道处理类也可能存在类似漏洞。果不其然。斩草要除根,痛快的方式,是在PO实体的CRUD服务类里封装一个方法,封装根据单号获取订单记录的操作,这样,各通道处理类调用这个方法,可有效规避类似漏洞。

以其中一个通道处理类的改动为例,见如下提交记录截图。

 

 

其实,单说系统操作回调处理这个应用场景,这种程序实现方式并不可取。怎么设计更合理呢?你先琢磨,我后续补充。

 

✅ 待续

 

有关两点之间直线最短,你写的是代码,我写的是艺术的更多相关文章

  1. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

    如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

  2. ruby-on-rails - Rails 源代码 : initialize hash in a weird way? - 2

    在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has

  3. ruby-on-rails - Rails 应用程序之间的通信 - 2

    我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此

  4. ruby - #之间? Cooper 的 *Beginning Ruby* 中的错误或异常 - 2

    在Cooper的书BeginningRuby中,第166页有一个我无法重现的示例。classSongincludeComparableattr_accessor:lengthdef(other)@lengthother.lengthenddefinitialize(song_name,length)@song_name=song_name@length=lengthendenda=Song.new('Rockaroundtheclock',143)b=Song.new('BohemianRhapsody',544)c=Song.new('MinuteWaltz',60)a.betwee

  5. ruby-on-rails - 浏览 Ruby 源代码 - 2

    我的主要目标是能够完全理解我正在使用的库/gem。我尝试在Github上从头到尾阅读源代码,但这真的很难。我认为更有趣、更温和的踏脚石就是在使用时阅读每个库/gem方法的源代码。例如,我想知道RubyonRails中的redirect_to方法是如何工作的:如何查找redirect_to方法的源代码?我知道在pry中我可以执行类似show-methodmethod的操作,但我如何才能对Rails框架中的方法执行此操作?您对我如何更好地理解Gem及其API有什么建议吗?仅仅阅读源代码似乎真的很难,尤其是对于框架。谢谢! 最佳答案 Ru

  6. ruby - 模块嵌套代码风格偏好 - 2

    我的假设是moduleAmoduleBendend和moduleA::Bend是一样的。我能够从thisblog找到解决方案,thisSOthread和andthisSOthread.为什么以及什么时候应该更喜欢紧凑语法A::B而不是另一个,因为它显然有一个缺点?我有一种直觉,它可能与性能有关,因为在更多命名空间中查找常量需要更多计算。但是我无法通过对普通类进行基准测试来验证这一点。 最佳答案 这两种写作方法经常被混淆。首先要说的是,据我所知,没有可衡量的性能差异。(在下面的书面示例中不断查找)最明显的区别,可能也是最著名的,是你的

  7. ruby-on-rails - `a ||= b` 和 `a = b if a.nil 之间的区别? - 2

    我正在检查一个Rails项目。在ERubyHTML模板页面上,我看到了这样几行:我不明白为什么不这样写:在这种情况下,||=和ifnil?有什么区别? 最佳答案 在这种特殊情况下没有区别,但可能是出于习惯。每当我看到nil?被使用时,它几乎总是使用不当。在Ruby中,很少有东西在逻辑上是假的,只有文字false和nil是。这意味着像if(!x.nil?)这样的代码几乎总是更好地表示为if(x)除非期望x可能是文字false。我会将其切换为||=false,因为它具有相同的结果,但这在很大程度上取决于偏好。唯一的缺点是赋值会在每次运行

  8. ruby - 寻找通过阅读代码确定编程语言的ruby gem? - 2

    几个月前,我读了一篇关于ruby​​gem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:

  9. ruby - Net::HTTP 获取源代码和状态 - 2

    我目前正在使用以下方法获取页面的源代码:Net::HTTP.get(URI.parse(page.url))我还想获取HTTP状态,而无需发出第二个请求。有没有办法用另一种方法做到这一点?我一直在查看文档,但似乎找不到我要找的东西。 最佳答案 在我看来,除非您需要一些真正的低级访问或控制,否则最好使用Ruby的内置Open::URI模块:require'open-uri'io=open('http://www.example.org/')#=>#body=io.read[0,50]#=>"["200","OK"]io.base_ur

  10. 程序员如何提高代码能力? - 2

    前言作为一名程序员,自己的本质工作就是做程序开发,那么程序开发的时候最直接的体现就是代码,检验一个程序员技术水平的一个核心环节就是开发时候的代码能力。众所周知,程序开发的水平提升是一个循序渐进的过程,每一位程序员都是从“菜鸟”变成“大神”的,所以程序员在程序开发过程中的代码能力也是根据平时开发中的业务实践来积累和提升的。提高代码能力核心要素程序员要想提高自身代码能力,尤其是新晋程序员的代码能力有很大的提升空间的时候,需要针对性的去提高自己的代码能力。提高代码能力其实有几个比较关键的点,只要把握住这些方面,就能很好的、快速的提高自己的一部分代码能力。1、多去阅读开源项目,如有机会可以亲自参与开源

随机推荐