文章目录
年底了大家都要述职,老板都会问:你这个方案,是否沉淀形成一套可复用解决方案?
今天就介绍关于一个业务:状态变多、条件分支增多、状态转换规则、依赖关系变复杂,导致代码难以维护,代码可重用性和可扩展性变差这个问题,一套可复用解决方案。
1 问题背景
产品
:来活啦,有用户反馈我们的APP没有线上退保证金功能,都在抖音上找到老板反馈了。
产品
:我们商户入驻状态有:未入驻、待入驻、已入驻、清退中、已清退。清退中又有子状态 商户申请关户中、统计商户有责货损中、待商户确认有责货损、申诉商户有责货损中、提现失败、提现成功、已清退等。
我这里简单画一下关户状态流转图
2 如何解决状态问题
在软件开发过程中,随着功能的不断迭代和添加,代码的可维护性往往会面临挑战。
我们有一个商户入驻的功能,功能也是由简单迭代到复杂,现在又要增加商户退出、重新入驻相关状态,状态转换逻辑也变得复杂,在这个迭代过程中,我们如何防止屎山代码形成?
2.1 解耦重构优化代码
项目初期,状态比较少,我们通过如下方法重构代码就可以解决问题。
下面是我们重构优化代码的例子。
重构前
:入驻方法很长,所有业务代码逻辑耦合在一起。
class A {
//入驻方法
public void join() {
if(未入驻过){
// 实人认证
//查询关联账号
...//其他业务逻辑
}else if(曾入驻过){
//查询关联账号
//计算售后率
...//其他业务逻辑
}
}
重构后
:提取出实人认证、计算售后率等方法。
class A {
//入驻方法
public void join() {
if(未入驻过){
// 实人认证
realPersonAuthentication();
...//其他业务逻辑
}else if(曾入驻过){
//计算售后率
calculatingAfterSalesRate();
...//其他业务逻辑
}
//查询关联账号
associatedAccount();
}
public void realPersonAuthentication() {
// 实人认证
}
public void associatedAccount() {
//查询关联账号
}
public void calculatingAfterSalesRate() {
//计算售后率
}
}
2.2 使用设计模式重构优化
使用状态模式、策略模式等都能帮助我们的代码清晰易读。
下面就是个状态模式解决不同入驻状态下商户拥有不同权限的例子,如果你的业务场景有如下特点,那么可以尝试使用状态模式
优化。
1)对象行为取决于状态。
比如商户是否可以送检行为取决于商户的已入驻状态。
2)状态转换逻辑复杂。
比如商户申请关户中、待确认货损状态才能撤销关户等。
3)避免大量条件语句。
这个业务场景,如果使用ifelse判断,需要写6个,代码也不好扩展维护。
业务规则:
状态模式类图:
2.3 使用状态机
如果你的状态很多,并且转换逻辑很复杂的时候,我们可以使用状态机,帮助我们进行状态管理。
2.3.1 思考状态机特点
看上面状态图,思考我们开发的其他场景的状态流转图,这些场景是不是有以下共同特点:
1)根据不同触发条件执行不同处理动作最后转变为新的状态(状态也有可能不变)。
2)状态间转换逻辑比较复杂。如果使用ifelse进行判断,业务复杂之后很难维护。
3)各个状态转换分散在不同方法中,很难清晰知道状态全部的流转规则。
2.3.2 总结归纳状态机特点
针对状态流转过程,其实是有很多相似的地方,我们可以简单总结归纳一下。
1)我们可以考虑将状态全部从业务层抽离,统一进行收口维护。
2)抽象状态流转规则, 比如:已入驻 状态转变为 清退中 状态,需要原状态是已入驻,并要完成一些业务操作(记录申请信息,通知商户、BD等等)。
3)我们将状态流转规则也进行统一维护(配置文件配置、代码里写死配置、数据库里配置等),这样便能清晰看到全部流转规则,简化状态管理。
3 状态机介绍
状态机其实很简单,不然也不会这么流行。由上面抽象总结出来的方法,其实就是状态机。状态机的概念很早就提出了,而且比Java语言本身还要早。