一次线上问题的思考

在线上商城的一次功能迭代中,我们遇到了一个线上问题。虽然很快解决,但是觉得这个问题在软件设计开发中非常典型,对问题产生的原因以及如何避免类似问题的产生做一次复盘分析

背景

商城的用户具有不同的会员等级,包括黄金会员、白银会员和普通会员。根据会员等级的不同,商品的价格策略也不同。具体来说,黄金会员购买商品时享受黄金会员价,普通会员购买时享受普通会员价,白银会员比较特殊购买时享受黄金会员价。

商品的后台管理功能只维护商品的黄金会员价和普通会员价,白银会员的价格显示和购买时的价格计算在业务代码中进行判断,如果是白银会员价格按照黄金会员执行。

image-20230708194435557

数据库设计:一个商品sku和会员价格存在一对多的关系

image-20230708200641157

产生问题

在优惠券功能迭代中,产品要求增加商品兑换券的功能,兑换券在进行商品购买时优惠金额 = 商品价格 - 0.01元,由于不同会员等级享受的商品价格不同,那么同一个兑换券对于不同的会员来说,优惠金额也就不一样,优惠金额需要根据使用优惠券时当前会员等级以及能够兑换的商品进行计算。

在功能开发时,遗漏了一个场景,那就是只计算了黄金会员和普通会员,而遗漏了白银会员,具体代码如下:

// 根据不同的会员等级,执行不同的会员价格
if (UserLevelEnum.GOLDEN_MEMBER.getCode().equals(level)) {
    return mallPrice;
} else {
    return memberPrice;
}

问题分析

在代码开发以及测试过程中为什么会遗漏了白银会员的场景?下面从几个维度分析一下问题产生的原因。

虽然知道用户的会员等级分为普通会员、白银会员和黄金会员,但是在商品价格的维护上只显示了普通会员价和黄金会员价,会使新接手的开发人员以及测试人员下意识的忽略白银会员的价格,开发和测试时关注点放在黄金会员和白银会员上。

虽然商品和会员价格是一对多的关系,但是白银会员价却并没有持久化在数据库中,而是通过业务代码的形式对会员等级进行判断,当白银会员购买时,取黄金会员的价格,重要的业务逻辑散落在业务代码的各个角落中,这在另一个层面中会使开发人员忽略白银会员的价格策略。

在开发人员或测试人员接手和熟悉一个新的系统时,他们通常会首先关注两个方面:实际功能的使用和数据库表之间的关联关系。如果这两个层面若有若无的对开发人员进行了一些错误的引导,那么出现问题也是在所难免。

问题思考

追寻功能的历史迭代,系统原本只有普通会员和黄金会员的等级,后来又新增了白银会员的等级,而白银会员比较特殊,白银会员购买商品时按照黄金会员的价格进行执行。在新增白银会员时,由于白银会员和黄金会员价格一样,产品并没有要求在后台管理页面中增加白银会员的价格维护,这并没有什么问题,因为按照当前业务逻辑来说相同数据填写两次,对操作人员来说并不友好。

而在代码实现时,开发人员可能也是参考产品的思路,直接在业务代码中进行会员等级的判断取黄金会员价格。

为什么会在业务代码中进行判断,而不是在会员等级价格策略表中新增白银会员的价格,可能下面几个原因:

  1. 在会员等级价格策略表中新增白银会员的价格策略,历史数据需要批量新增
  2. 新增修改商品时,因为页面并没有白银会员价格,后端需要对白银会员价格进行处理
  3. 在业务代码中进行判断改动较小,当时可能只涉及少量接口,工作量比较小

当然从历史背景的角度出发,选择从业务代码中进行判断的方式并不能说是错的,他也是实现业务功能的一种方式,从结果上说也达成了产品和业务的需求,但是从系统设计上说并不是最好的方式。

黄金会员和普通会员的价格持久化在数据库中,而白银会员的价格策略却是在业务代码中,这违背了开发人员的直观认知,从软件设计的角度讲,这其实也违背了最小惊奇原则

其次重要的业务代码散落在各个查询接口中,并没有一个业务对象收敛聚合商品的价格策略,而且商品对象中充斥着黄金会员价:mallPrice,普通会员价:memberPrice这种变量,唯独缺失了白银会员价的变量字段,会让人直观的认为只有黄金会员和普通会员这两种价格策略。

改进和规避

其实以上的内容已经将问题出现的原因分析的比较清楚,无非是各种若有若无的错误暗示和引导将开发人员引入了坑中,那么如何在软件设计和开发中避免类似的错误问题呢?

  1. 对于系统场景的软件设计最好以一贯之,像会员等级对应价格的这种策略不应该一部分在数据库一部分在业务代码中,要么数据库一对多持久化要么业务代码中有相应的业务对象进行收敛。
  2. 在功能设计开发时,软件的可维护性还是应该着重考虑,在有多种实现方案时,不应因为工作量的多少而选择了取巧的方式,这样最后只会给其他维护人员造成困扰。
  3. 开发和测试人员还是应该尽量将场景吃透覆盖,对有一些似有似无的功能还是应该进行详细的功能操作和代码实现分析。
posted @ 2023-07-08 21:17  ~鲨鱼辣椒~  阅读(23)  评论(0编辑  收藏  举报