略没效果,颗粒易套娃,如何寻找逻辑复用的代码设计边界?

举报
叶一一 发表于 2023/08/28 19:02:23 2023/08/28
1.2k+ 2 1
【摘要】 为什么提边界?除了上面提到的,有些过度设计导致的不容易找到修改位置,代码阅读不便。还有一个同样重要的问题。那就是老代码改动不全或现有功能不兼容。如果没注意到这个问题,且提测的时候没有进行特别的说明,可能导致线上Bug的发生。复用设计,不同之处也很重要这个单拎出来写,是因为之前吃过亏。前面提到了功能设计可能会带来的三个问题,其中第一个问题,对于复杂的功能,一味的关注相同之处,去做逻辑复用,导致...

为什么提边界?

除了上面提到的,有些过度设计导致的不容易找到修改位置,代码阅读不便。
还有一个同样重要的问题。那就是老代码改动不全或现有功能不兼容。

如果没注意到这个问题,且提测的时候没有进行特别的说明,可能导致线上Bug的发生。

复用设计,不同之处也很重要

这个单拎出来写,是因为之前吃过亏。

前面提到了功能设计可能会带来的三个问题,其中第一个问题,对于复杂的功能,一味的关注相同之处,去做逻辑复用,导致后续出现了新增功能有遗漏的情况。

我真的碰到,才在开头处提到这种情况。

场景描述

简单描述一下之前的功能:

商品管理中绑定的赠品,在订单管理中同样有。

虽然入口不同,但是通过入口跳转的赠品列表相似。

商品管理跳转到赠品列表可进行增、删、改、导出操作。

订单管理跳转到赠品列表只可以进行导出操作。

对于数据请求则是:

商品管理和订单管理是不同的接口,且接口请求入参不同。

第一期开发的时候,我将绑定赠品的页面设计为一个页面,根据页面链接中携带的参数不同,区分可进行的操作。

在第二期的需求中,额外增加了许多功能,其中一个需求是商品如果上架之后,不可对赠品进行增、删、改操作。

代码加好之后,我忽略了现有功能,所以上线之后出现了一个比较严重的情况:非上架状态的商品跳转赠品页,展示了全部赠品。

好在仅为后台展示,不是购买页面真实的赠品。但是如果是敏感数据,可能会导致泄漏的情况。

一期设计

来看一下第一期的设计

1、商品管理跳转处理

const goToGift = record => {
  history.push(`/gift?type=goodManage&goodId=${record.id}`);
};

2、赠品页

const getList = () => {
  let params = {};
  let api=api1;
  // 商品管理跳转传参
  if (goodManage) {
    params.goodId = goodId;
  }
  // 订单管理跳转传参
  if (orderView) {
    params.orderId = orderId;
    api = api2;
  }
  api(params).then(res => {
    setList(res.list);
  });
};

二期补充

1、商品管理跳转处理

跳转前做了类区分,其中当跳转类型是goodView,不展示增、删、改的操作。

const goToGift = record => {
  record.type = record.status === 1 ? 'goodManage' : 'goodView';
  history.push(`/gift?type=${record.type}&goodId=${record.id}`);
};

但是我忽略了赠品页请求数据时的入参的处理,所以导致返回了全部数据。

优化

有两种优化方案。

1、方案一:把赠品页的请求改一下,请求入参不做区分,有值就传。

const getList = () => {
  let params = {
    goodId: goodId,
    orderId: orderId,
  };
  let api=api1;
  // 订单管理跳转传参
  if (orderView) {
    api = api2;
  }
  api(params).then(res => {
    setList(res.list);
  });
};

2、方案二:不同入口跳转的页面从一个拆分成多个。

不单单因为数据获取更加安全,还有很重要的一点,随着业务的发展,赠品页复杂程度增加。

因为业务拓展是间断的,所以再次开发时,已经忘记了一些之前的功能。再次阅读也比较困难,老代码改动也会影响现有功能。

const goToGift = record => {
  if (record.status === 1) {
    return history.push(`/gift?goodId=${record.id}`);
  } else {
    return history.push(`/gift/view?goodId=${record.id}`);
  }
};

所以我后来选择了方案二,做了一次拆分。

相似度较高、复杂性也很高的功能,推荐按照性质分类,区分为不同的板块。采用相似的功能设计成公共组件的方式,实现逻辑复用。且各个板块修改不同之处互不影响。

锦瑟难解,边界难觅

如果说边界到底在哪,我很难说出类似“符号看象限”这样的数学口诀或者定律。我一般会根据业务走向做适当思维发散。

不过,我尽量总结几个大致的思路:

  • 不同之处,尽量不用条件判断去处理,在各自的函数体中处理,做到"物理"隔离。
  • 相同之处,增删改需要覆盖全部引用的代码模块。比如A、B、C三个引用代码模块,只有A、B需要,建议额外增加逻辑复用处理,不再原来的复用代码处修改。如果必须再原处修改,做好文字注释。

总结

写这篇文章,还是主要想跟大家分享我之前做的不合理的开发设计的经验。

这个念头一起,再碰上每日"三省吾身"的时刻,思维一发散。当即决定写一篇文章。

文章内容其实做了修改和删减,而其中一些观点,虽然我反复进行了审视,但并不能保证百分百正确。

欢迎留言讨论。



作者介绍

非职业「传道授业解惑」的开发者叶一一。

《趣学前端》、《CSS畅想》等系列作者。华夏美食、国漫、古风重度爱好者,刑侦、无限流小说初级玩家。

如果看完文章有所收获,欢迎点赞👍 | 收藏⭐️ | 留言📝。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

作者其他文章

评论(2

抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。