美文网首页
新需求带来坏味道:一次驳回的实现

新需求带来坏味道:一次驳回的实现

作者: GuangHui | 来源:发表于2022-10-04 23:01 被阅读0次

我们的系统里有这样一个功能,内容作品提交之后要由相应的编辑进行审核。既然有审核,自然就有审核通过和不通过的情况,这是系统中早早开发完成的功能。

有一天,新的需求来了:驳回审核通过的章节,让作品的作者重新修改。造成作品需要驳回的原因有很多,比如,审核标准的调整,这就会导致原先通过审核的作品又变得不合格了。

在实现这个需求之前,我们先来看看代码库里已经有怎样的基础。首先,系统里已经有了审核通过和审核不通过的接口。

PUT /chapter/{chapterId}/review
DELETE /chapter/{chapterId}/review

在这个设计里,将章节(chapter)的审核(review)当作了一个资源。在创建章节的时候,章节的审核状态就创建好了。审核通过,就相当于对这次审核进行了修改,而审核不通过,就相当于删除了这个资源。

对应着这两个接口,就有两个对应的服务接口:

class ChapterService {
public void approve(final ChapterId chapterId) {
...
}

public void reject(final ChapterId chapterId) {
...
}
}

顾名思义,approve 函数对应着审核通过,而 reject 对应着审核不通过。相应地,章节上有一个状态字段,标识现在章节处于什么样的状态。章节是待审核、审核通过,还是审核不通过,就是通过这个字段标记出来的。

class Chapter {
private Status status = Status.PENDING;

public void approve() {
this.status = Status.APPROVED;
}

public void reject() {
this.status = Status.REJECTED;
}
}

好,我们已经知道了这些基础了,那驳回的需求该怎么设计呢?

既然增加了一个驳回的功能,那就增加一个驳回的接口,然后,在服务中增加一个驳回的服务,最后,再在状态中增加一个驳回的状态。这么做,听上去非常合理,你是不是已经按捺不住自己蠢蠢欲动的双手,准备写代码了呢?

且慢!我嗅到了一丝坏味道,这个坏味道来自于我们要增加一个接口。来一个新需求,增加一个新接口,对于很多人来说,这是一种常规操作。但我们必须对新增接口保持谨慎。接口,是系统暴露出的能力,一旦一个接口提供出去,你就不知道什么人会以什么样的方式使用这个接口。

我们常常看到很多系统有很多接口,如果你仔细梳理一番,就会发现,有很多接口提供类似的功能,这会让初次接触到系统的新人一脸茫然。即便你打算对系统进行清理,当清理掉一个你以为根本没有人用的接口时,就会有人跑出来告诉你,这个接口调整影响了他们的业务。

所以,我们必须对接口的调整慎之又慎。最好的办法就是从源头进行限制,也就是说,当我们想对外提供一个接口时,我们必须问一下,真的要提供一个新接口吗?

回到这个案例上,我们面对这个需求的第一反应和大多数人一样,也是增加一个新的接口。但是,是否真的要增加一个新的接口呢?如果不增加新接口,这就意味着要复用已有的接口。但复用的前提是:新增的业务动作是可以通过已有的业务来完成的,或是对已有业务进行微调就可以。

那么,到底是需要新增,还是复用,真正要回答这个问题,还是要回到业务上。
在原有的业务中,审核通过会进入到下一个阶段,而审核不通过,就会退回到作者那里进行修改。那驳回之后呢?它也会要求作者去修改。

说到这里,你就不难发现了,驳回的动作和审核不通过,二者的后续动作是一样的。它们的差别只是起始的状态,如果原来的状态是待审核,经过一个审核不通过的动作,状态就变成了审核不通过;而如果原来的状态是审核通过,经过一个驳回的动作,状态就变成了驳回。所以,我们完全可以复用原来的审核不通过接口。

既然是复用接口,所有的变化就全部都是内部变化了,我们可以根据章节当前的状态进行判断,设置相应的状态。

具体到代码上,我们既不需要增加驳回的接口,也不需要增加驳回的服务,只需要在 Chapter 类内部进行修改,代码改动量比原先预期的就小了很多。其代码结构大体如下所示:

class Chapter {
private Status status = Status.PENDING;
...

public void reject() {
if (status == Status.PENDING) {
this.status = Status.REJECTED;
return;
}

if (status == Status.APPROVED) {
...
.
}
}
}

按照这个理解,我们只要增加一个驳回的状态,在当前状态是审核通过时,将这个新状态赋值上去就可以了。看上去,我们已经把这次要改动的代码限制在一个最小的范围。但其实,我还想再问一个问题,我们真的需要这么一个状态吗?

是否增加一个驳回的状态,回答这个问题还是要回到业务上,驳回后续的处理与审核不通过的状态有什么不同。

按照产品经理本来的需求,他是希望做出一些不同来,比如,处于审核不通过的状态,编辑端是无法查看的,而处于驳回状态的,编辑是可以查看的。但在当前的产品状态下,我们是否可以将二者统一起来呢?也就是说,都按照审核不通过来处理呢?

产品经理仔细想了想,觉得其实也可以,于是,两种不同的状态在这里得到了统一,也就是说,我们根本没有增加这个驳回的新状态。

事情说到这里,你就会发现,在这次的业务调整中,后端服务的代码其实没有做任何修改,只是前端的代码在需要驳回时增加了一个对审核不通过的调用,而所有这一切的起点,只是我们对于增加一个新接口的嗅觉。

相关文章

  • 新需求带来坏味道:一次驳回的实现

    我们的系统里有这样一个功能,内容作品提交之后要由相应的编辑进行审核。既然有审核,自然就有审核通过和不通过的情况,这...

  • 设计坏味道

    设计坏味道 1. 设计坏味道概述 为何要关注坏味道,因为坏味道影响了软件的质量;给项目的开发、维护、扩展等带来了影...

  • 函数式接口 + Lambda实现函数指针

    坏味道: 坏味道:相同的代码多次出现 函数式接口 + Lambda实现类似功能: 函数式接口定义: 配合Lambd...

  • 多态枚举

    迭代1:快速实现 需求1:实现一个计算器,完成加减乘除运算 这是一个很糟糕的设计,存在很多的坏味道。 类型不安全 ...

  • 变化是美妙的旅程

    1,幸好世界变化万千,因为变化会带来新的需求,我们在应对变化带来的新需求同时,会提升我们应对变化的能力,应对变化本...

  • Flowable 实现节点驳回

    在Flowable开发中可能遇到某个节点审批出问题需要驳回该节点任务 遇到此问题可以参考以下代码需要自己判断只能驳...

  • 坏味道与重构手法

    坏味道(英文)坏味道(中文)页码常用重构Alternative Classes with Different In...

  • 识别代码中的坏味道(三)

    前两篇文章 《识别代码中的坏味道(一)》 和 《识别代码中的坏味道(二)》 中已经介绍了 18 个代码坏味道。《重...

  • 痛,更痛,哭泣,完成,微笑

    2016-09-20 一个小任务,驳回,驳回,再驳回,修改,修改,再修改。 第一次,有点尴尬,因为确实有一些应付任...

  • 代码的坏味道

    0. 本章内容导图 1. 常见的代码坏味道 (1)重复代码 坏味道中首当其冲的就是重复代码,重复代码是万恶之源,如...

网友评论

      本文标题:新需求带来坏味道:一次驳回的实现

      本文链接:https://www.haomeiwen.com/subject/uiyuartx.html